[洛谷P1714]切蛋糕
阿新 • • 發佈:2017-11-09
return 連續 inline -- 個數 digi tdi logs etc
題目大意:給你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]切蛋糕