题解
- 这其实是一道单调队列优化区间dp问题,对于这个序列,我们可以划分为n个区间,每个区间代表以ai结尾,长度不超过m的子序列和,我们只需要遍历一遍每个集合,找到每一个集合中的最大值,那么就可以更新出这个序列的最大值
- 如何找每个集合中的最大值呢,最大值就是要求出以a[k]结尾,长度不超过m的子序列和最大,求区区间和我们可以用前缀和,s[k]-s[k-j] (1<=j<=m) ,要想使所求值最大,那么就要使s[k-j]最小 ,所以问题就转化成求一个滑动区间的最小值问题,我们就可以用单调队列做优化
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 300010, INF = 0x3f3f3f3f;
int n, m;
int s[N], q[N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &s[i]);
s[i] += s[i - 1];
}
int res = -INF;
int hh = 0, tt = 0;
for (int i = 1; i <= n; i++) {
if (q[hh] < i - m) hh++;
res = max(res, s[i] - s[q[hh]]);
while (hh <= tt && s[i] <= s[q[tt]]) tt--;
q[++tt] = i;
}
printf("%d\n", res);
return 0;
}