1. 程式人生 > >2018.09.23 孫悟空大戰鯉魚精(單調佇列優化dp)

2018.09.23 孫悟空大戰鯉魚精(單調佇列優化dp)

傳送門 一道帶了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;
}