“敢问路在何方?路在脚下!”——《敢问路在何方》(阎肃)
“英雄名不堪得,何必教我混沌徒费口沫……”——《九九八十一》
话说为了普度众生,如来决定让大乘佛法流传于世。正好,如来的二弟子由于听课不认真,被如来打入凡间,成为了唐朝高僧玄奘,来完成西天取经以传播佛法到大唐的使命。在路上,他得到了三个弟子的帮助——齐天大圣孙悟空,天蓬元帅猪八戒,卷帘大将沙和尚,经历了九九八十一难,终于成功弘扬佛法,功成正果。
现在假设你是如来佛祖。你知道唐僧从长安到天竺的路上会经历n里路,并且你准备了k个可能经历的磨难。(在真实的《西游记》中,n=108000,k=80)
现已知第i里路上设置的一个磨难,会对取经的效果带来ci的收益。由于你不准备让唐僧一行过于劳累,你决定下一个磨难到上一个磨难至少要走过p里;但是,你也不准备让他们过于安逸,你又决定下一个磨难到上一个磨难至多不能走过q里。另外,第i里路上设置的磨难,对应着一个具有玄机的数字di。考虑到某些磨难之间存在在功德上相互抵消的关系,如果相邻的两个磨难的di均具有某个给定的因子t,它们会共同带来-z的损失。
现在请你求出最佳安排方式下,收益的最大值。(默认唐僧从长安出发的时候是第0里,经历了第0个磨难,当前收益为0。设置的磨难数可以是0到k之间的任何整数。)
注意,只有磨难之间有限制,终点不一定设置了磨难。
第一行六个正整数n,k,t,p,q,z。
接下来一行有n个正整数ci。
接下来一行有n个正整数di。
输出文件包含一行一个整数,表示收益的最大值。
8 3 3 2 3 1
8 9 11 6 7 5 6 8
1 2 3 3 3 1 3 3
24
【样例说明】
3个劫难分别位于第3,5,8里。总收益为11+7+8-1-1=24.
注意第一个劫难由于受到第0个劫难的制约只能选择第2或3里,而最后一个劫难未受后方制约。
【数据范围与约定】
该题目一共有20个数据点。
对于第1-3个数据点,n<=15,k<=6。
对于第4-8个数据点,n<=100,k<=50。
对于第9-12个数据点,n<=500,k<=100。
对于第13-17个数据点,n<=4000,k<=300。
对于第18-20个数据点,n<=10000,k<=800。
对于奇数号数据点,t>max{di}。
此外,对所有的数据,都有k<=n,1<=ci<=10^6,z<=10^6, di<=10^9,1<=p<=q<=n。
#include<bits/stdc++.h> #pragma GCC optimize(2) #pragma GCC optimize(3) #define _I inline #define _R register #define ll long long #define ull unsigned long long #define mod 1000000007 #define eps 1e-5 #define INF 0x3f3f3f3f3f3f3f3f #define memset(x,y) memset(x,y,sizeof(x)) #define memcpy(x,y) memcpy(x,y,sizeof(x)) using namespace std; //char buf[1<<19],*p1=buf,*p2=buf; //#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<19,stdin),p1==p2)?EOF:*p1++) const ll N=10005; ll n,k,t,p,q,z,ans=-INF,maxx; ll c[N],d[N],f[N][2],Q[N][2],l[2],r[2]; _I ll read(){ ll x=0;char ch=getchar();bool f=0; while(ch>'9'||ch<'0')f|=(ch=='-'),ch=getchar(); while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); f&&(x=-x); return x; } int main(){ // freopen("journey2.in","r",stdin); // freopen("journey.out","w",stdout); n=read();k=read();t=read();p=read(),q=read(),z=read(); for(_R ll i=1;i<=n;++i)c[i]=read(); for(_R ll i=1;i<=n;++i)d[i]=read(); for(_R ll i=p;i<=q;++i)f[i][1]=c[i],ans=max(ans,f[i][1]); for(_R ll j=2;j<=k;++j){ l[0]=l[1]=1;r[0]=r[1]=0; for(_R ll i=1;i<=n;++i){ f[i][j&1]=-INF; if(i-p>=0){ if(d[i-p]%t==0){ while(l[1]<=r[1]&&f[i-p][(j&1)^1]>=f[Q[r[1]][1]][(j&1)^1])--r[1]; Q[++r[1]][1]=i-p; } else{ while(l[0]<=r[0]&&f[i-p][(j&1)^1]>=f[Q[r[0]][0]][(j&1)^1])--r[0]; Q[++r[0]][0]=i-p; } } while(l[1]<=r[1]&&Q[l[1]][1]<i-q)++l[1]; while(l[0]<=r[0]&&Q[l[0]][0]<i-q)++l[0]; if(d[i]%t==0){if(l[1]<=r[1])f[i][j&1]=f[Q[l[1]][1]][(j&1)^1]+c[i]-z;} else{if(l[1]<=r[1])f[i][j&1]=f[Q[l[1]][1]][(j&1)^1]+c[i];} if(l[0]<=r[0])f[i][j&1]=max(f[i][j&1],f[Q[l[0]][0]][(j&1)^1]+c[i]); ans=max(ans,f[i][j&1]); } } printf("%lld",ans); return 0; }