码迷,mamicode.com
首页 > 其他好文 > 详细

[洛谷P1714]切蛋糕

时间:2017-11-09 22:40:15      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:cpp   队列   str   复杂   连续   strong   amp   def   color   

题目大意:给你n个数,要你求一段长度不超过k的、和最大的连续子序列,问你最大的和是多少。

解题思路:单调队列+前缀和优化。

可以发现,i到j的和与k到j的和,当j变化时,这两个和的相对大小关系是不变的。

我们用单调队列保存与当前第i个位置距离小于k(等于则不能加到)的位置,并让这个位置加到i的和单调递减。

这样就能保证每次从队头弹出时,之后的和仍是最大。

求一段连续序列的和就用到前缀和优化。

总时间复杂度$O(n)$。

C++ Code:

#include<cstdio>
#include<cctype>
#define N 500005
int n,k,a[N],sa[N],q[N<<1],h,t;
inline int max(int a,int b){return a<b?b:a;}
inline int readint(){
    char c=getchar();
    bool b=false;
    for(;!isdigit(c);c=getchar())b=c==‘-‘;
    int d=0;
    for(;isdigit(c);c=getchar())
    d=(d<<3)+(d<<1)+(c^‘0‘);
    return b?-d:d;
}
int main(){
    n=readint(),k=readint();
    sa[0]=0;
    for(int i=1;i<=n;++i)sa[i]=sa[i-1]+(a[i]=readint());
    int ans=max(0,a[1]);
    if(k==1){
        for(int i=1;i<=n;++i)ans=max(ans,a[i]);
        printf("%d\n",ans);
        return 0;
    }
    q[1]=h=t=1;
    for(int i=2;i<=n;++i){
        while(q[h]+k<=i)++h;
        while(h<=t&&a[i]>sa[i]-sa[q[t]-1])--t;
        q[++t]=i;
        ans=max(ans,sa[i]-sa[q[h]-1]);
    }
    printf("%d\n",ans);
    return 0;
}

 

[洛谷P1714]切蛋糕

标签:cpp   队列   str   复杂   连续   strong   amp   def   color   

原文地址:http://www.cnblogs.com/Mrsrz/p/7811350.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!