题意: 给定长度为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 }