• P2034选择数字题解


    题目链接:在这里~

    题目描述:

    给定一行n个非负整数a[1]..a[n]。现在你可以选择其中若干个数,
    但不能有超过k个连续的数字被选择。你的任务是使得选出的数字的和最大。

    输入格式:

    第一行两个整数n,k
    
    以下n行,每行一个整数表示a[i]。

    输出格式:

    输出一个值表示答案。

    思路:考虑反面,不能有超过k个连续的数字被选,等价于连续的k+1个数字中必须删一个,考虑如何去删数字,f[i]表示删了第i个数字的最小代价,f[i]可由(i-k-1)--->(i-1)转移过来,即在i前面的k+1个数字间,必须删一个,且 当前决策对后面无影响。n=1e5,O(n^2)的算法是过不去的,所以可以单调队列优化。

    代码:

    #include<iostream> 
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define R register
    #define ll long long int 
    using namespace std;
    const int N=1e5+5;
    ll n,k,a[N],f[N],Min=1e16,fir=1,x[N],ans,head=1,tail=0;
    int main(){
        scanf("%lld%lld",&n,&k);
        for(R int i=1;i<=n;++i){
        scanf("%lld",&a[i]);
        ans+=a[i];f[i]=Min;
        }
        f[0]=0;//第i个被删的最小代价
        for(R int i=1;i<=n;++i){
            if(i<=k+1)
            f[i]=a[i];
            else
            f[i]=f[x[head]]+a[i];
            while(head<=tail&&x[head]<i-k)head++;
            while(head<=tail&&f[x[tail]]>f[i])tail--;
            x[++tail]=i;
        }
        for(R int i=n;i>=n-k;--i)
        Min=min(Min,f[i]);
        printf("%lld",ans-Min);
        return 0;
    }
  • 相关阅读:
    Android_PopupWindow提示框
    视图字段对应属性列表
    odoo 关系字段(关联关系)
    odoo字段属性
    odoo xml中添加数据的数字代表含义
    odoo 常用模型的简写
    odoo标识符
    odoo 权限文件说明
    Odoo的菜单项
    Odoo的 数据添加修改删除代码和对应的方式
  • 原文地址:https://www.cnblogs.com/sky-zxz/p/9785130.html
Copyright © 2020-2023  润新知