这是一道很基础很基础的单调队列的题,嗯很适合我来写。
这道题其实和单调队列裸题——滑动窗口(详见刘汝佳白书)是一样的,只要稍微改一下思考的方向。
一开始可以这么想,先预处理出前缀和,在前缀和数组pre[]上做文章。
对于每个i > s,即求出以每个i结尾的最优区间,再取最优即可。
所以就落到了求每个以i(i >= s)结尾的最优区间,我们有前缀和,所以就是求出前面某一段的最小值即可(其实不止单调队列这一种方法了),
“某一段”只要满足使这个以i结尾的区间长度在s到t之间即可。
“某一段”只要满足使这个以i结尾的区间长度在s到t之间即可。
那就是pre[i-t+s] ~ pre[i-s]之间的最小值了,用单调队列可以很快的处理。
这不就是滑动窗口了么,窗口长度是t-s,只不过求出最小值后再用pre[队尾+s]相减即可。
#include <cstdio>
#include <algorithm>
#define M 1000005
using namespace std;
int a, n, s, t, f, b, l, ans = -(1<<30);
int pre[M], q[M];
int main()
{
freopen("ggame.in","r",stdin);
freopen("ggame.out","w",stdout);
scanf("%d %d %d", &n, &s, &t);
l = t - s;
for(int i = 1; i <= n; i++){
scanf("%d", &a);
pre[i] = pre[i-1] + a;
}
ans = pre[s];
for(int i = 1; i <= n-s; i++){
while(f < b && pre[i] <= pre[q[b-1]]) b--;
q[b++] = i;
while(f < b && q[b-1] - q[f] > l) f++;
ans = max(ans, pre[i+s] - pre[q[f]]);
}
printf("%d", ans);
}
不过我一开始不是这么想的,在我最初的想法因为细节wa掉(哎,这是病,得治!)的时候才这么做的。
我一开始想的是求出的数组pre[i]代表的是以i结尾,长度为s-1的区间和。
之后从s开始循环i,记录上一个(循环为i-1)最佳区间的左端点是pos,右端点既是i-1,
此时求的是以i为右端点的区间的左端点,
如果i-pos+1没有超过t,而且上一个最优值-pre[i-1] > 0(这一段就是我们时刻求的,是以每个i结尾的最优区间减去固定的pre[i]的那一小段,我们每一次求都是固定了一个长度s-1的区间,这个就是预处理的pre[]), 那么pos~i也就是最优的,
(如果上一个最优值pre[i-1] <= 0 那就可以只取第i-s+1个数即可)
否则,那么暴力枚举pos。
如此便可求出答案。
</pre></div><pre class="cpp" name="code">#include <cstdio>
#include <algorithm>
#define M 1000005
using namespace std;
int n, s, t, pos, cul, ans;
int a[M], pre[M];
int main()
{
freopen("ggame.in","r",stdin);
freopen("ggame.out","w",stdout);
scanf("%d %d %d", &n, &s, &t);
for(int i = 1; i <= n; i++) scanf("%d", a+i);
for(int i = 2; i <= s; i++) pre[s] += a[i];
for(int i = s+1; i <= n; i++) pre[i] = pre[i-1] + a[i] - a[i-s+1];
cul = ans = pre[s] + a[1]; pos = 1;
for(int i = s+1; i <= n; i++){
if(pos == 1 || i-pos+1 > t){
int mx = -(1<<30), sum = 0;
for(int j = 0; j < t-s+1 && i-s+1-j > 0; j++){
sum += a[i-s+1-j];
if(sum > mx){
mx = sum; pos = i-s+1-j;
}
cul = mx+pre[i];
}
} else if(cul-pre[i-1] < 0){
pos = i-s+1, cul = pre[i] + a[i-s+1];
} else{
cul += a[i];
if(cul < a[i]) cul = a[i];
}
ans = max(ans, cul);
}
printf("%d", ans);
}