原题传送门
有点类似于前缀和的思想,不过这题如果纯前缀和基本相当于暴力,肯定过不去
#include<bits/stdc++.h>
using namespace std;
const int N = 300010, INF = 1e9;
int n, m;
int q[N], s[N];
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ ){
scanf("%d", &s[i]);
//s[i]记录的是从s[1]到s[i]的数值之和
s[i] += s[i - 1];
}
int res = -INF, tt = 0, hh = 0;
//单调队列
for(int i = 1; i <= n; i ++ ){
//q单调队列内存的是下标
if(q[hh] < i - m) hh ++ ;//如果队首元素已经超出单调队列范围,就让他出队
res = max(res, s[i] - s[q[hh]]);
//单调队列是单调上升的,所以在长度不超过m的单调队列内最小值是用队首元素记录的
//用s[i]减去队首元素即可得这段区间内最大的连续子序列和
while(hh <= tt && s[i] <= s[q[tt]]) tt -- ;//单调队列内的元素是递增的,所以如果队尾元素大于新加入的元素,就需要让队尾元素出队
//以此维持单调队列内单调上升的序列
q[ ++ tt] = i;//新元素入队
}
cout<<res<<endl;
return 0;
}