描述
孙悟空大战鲤鱼精,孙悟空在通天河遇到鲤鱼精,他嫉恶如仇,看见妖精就手痒(忘了自己是妖精)。但是鲤鱼精知道孙悟空的厉害,在孙悟空来到通天河,鲤鱼精就跑到了河对面。于是孙悟空就去追鲤鱼精。 我们可以把通天河看成一列格子,从0编号到N,孙悟空只能从小号格子到大号格子,当他在第i号格子,他移动的时候只会到[i+L,i+R]的某一格。每一个格子有一个魔法数Wi,第0号格子指数诶0,当孙悟空在某一格停留时就会获得这个魔法值Wi。孙悟空希望通过通天河时获得最大的魔法,这样他才能狠打一下鲤鱼精,可是孙悟空战斗力高,脑袋不咋地(猴脑),他希望你来帮他计算如何达到对岸,他开始在第0号 格。他只要最后一步落在的位置编号大于了N就算通过了通天河
输入
第1行:3个正整数N, L, R
第2行:N+1个整数,第i个数表示编号为i-1的格子的魔法数A[i-1]
输出
第1行:一个整数,表示最大魔法值。保证不超过2^31-1 第2行:空格分开的若干个整数,表示孙悟空前进的路线,最后输出-1表示到达对岸
样例输入
5 2 3
0 12 3 11 7 -2
样例输出
11
0 3 -1
提示
对于60%的数据:N <= 10,000
对于100%的数据:N <= 200,000
对于所有数据 -1,000 <= A[i] <= 1,000且1 <= L <= R <= N
一道带了spj的单调队列优化dp。
注意元素入队和出队的条件。
代码:
#include<bits/stdc++.h>
#define N 200005
using namespace std;
inline int read(){
int ans=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans*w;
}
inline int write(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar((x%10)^48);
}
int n,l,r,pred[N],a[N],f[N],q[N],print[N],hd,tl,tot=0;
int main(){
n=read(),l=read(),r=read(),hd=1,tl=0;
for(int i=0;i<=n;++i)a[i]=read();
for(int i=1;i<=n;++i)f[i]=-1e9;
for(int i=1;i<=n;++i){
while(hd<=tl&&q[hd]<i-r)++hd;
if(i>=l){
while(hd<=tl&&f[q[tl]]<f[i-l])--tl;
q[++tl]=i-l;
}
if(hd<=tl)f[i]=f[q[hd]],pred[i]=q[hd];
f[i]+=a[i];
}
int ans=n-r+1;
for(int i=n-r+2;i<=n;++i)if(f[i]>f[ans])ans=i;
write(f[ans]),puts("");
for(int i=ans;i;i=pred[i])print[++tot]=i;
print[0]=-1,print[++tot]=0;
for(int i=tot;~i;--i)write(print[i]),putchar(' ');
return 0;
}