切蛋糕

题意: 给定长度为n的序列 给定数m

  求此序列中长度不大于m的最大区间和 

  区间元素可能为负

   (洛谷1714)

思路: 区间求和可以想到前缀和

            这里维护一个前缀和单调递增的序列

            若当前元素前缀和大于栈顶元素前缀和 入队

            否则将比当前元素前缀和大的元素全部弹出 再入队

            还需要删除过期的元素(与当前元素的距离已经大于m了)

            再用队尾元素的前缀和减去队首元素的前缀和更新答案 即为最优

code

 1 #include<iostream>
 2 #include<cstdio>
 3 #define M 500010
 4 #define go(i,a,b) for(register int i=a;i<=b;i++)
 5 using namespace std;
 6 int read()
 7 {
 8   int x=0,y=1; char c; c=getchar();
 9   while(c<'0'||c>'9') {if(c=='-') y=-1;c=getchar();}
10   while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
11   return x*y;
12 }
13 int a[M],s[M],q[M*4];
14 int n,m,h,t,ans;
15 int main()
16 {
17   n=read();m=read(); go(i,1,n) a[i]=read(),s[i]=s[i-1]+a[i];
18 
19   go(i,1,n)
20     {
21       while(s[q[t]]>s[i]&&t>h) t--;
22       q[++t]=i;
23       while(q[h]<i-m) h++;
24       ans=max(ans,s[i]-s[q[h]]);
25     }
26 
27   printf("%d",ans);
28   return 0;
29 }
光伴随的阴影
原文地址:https://www.cnblogs.com/forward777/p/10125113.html