初始思路
这道题一看就是(dp)题,设(f[x])是到(x)位置的最大冰冻效果,转移的话就是:(f[x]=max(f[k])+val[x] -- k∈[x-r,x-l]),但是由于数据范围的原因,裸的(dp)是不行的,我们发现我们求的是最大值,而且有转移方程是得知是一个最值加上一个定值,所以我们考虑维护这个最值,那么就自然地想到单调队列.
进阶思路
我们用单调队列维护最大值,就要保证队列的元素是单调递减的,在转移的时候也不用去找(k∈[x-r,x-l])这个范围,直接去队列的队首元素即可.
代码
#include<bits/stdc++.h>
using namespace std;
int n,l,r,a[2000010],f[2000010];
int ans=-INT_MAX;
deque < int > q;
int main(){
scanf("%d%d%d",&n,&l,&r);
for(int i = 1;i <= 2 * n;i++)f[i] = -INT_MAX;
for(int i = 0;i <= n;i++) scanf("%d",&a[i]);
for(int i = 0;i <= n;i++){
while(!q.empty() && f[i] > f[q.back()]) q.pop_back();
q.push_back(i);
while(!q.empty() && q.front() < i - r + l)
q.pop_front();//超过了可以跳跃的范围,就直接弹出
f[i + l] = f[q.front()] + a[i + l];//单调队列维护的最大值在队头
}
for(int i = n + 1;i <= n + l;i++)//因为最终会跳出去,所以去外面找,初始化的时候也要注意多初始化一倍
ans = max(ans,f[i]);
printf("%d
",ans);
return 0;
}