zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    原理Lambda表达式
    关于Web.config的debug和release.config文件
    利用GeoIP数据库及API进行地理定位查询 Java
    JSONP跨域的原理解析
    如何处理JSON中的特殊字符
    IIS下防止mdb数据库被下载的实现方法
    点击文字选中radio
    关于微信40029错误
    nopcommerce的WidgetZones
    js判断移动终端(手机浏览器)
  • 原文地址:https://www.cnblogs.com/sky-zxz/p/9785130.html
Copyright © 2011-2022 走看看