首先这题可以肯定的是朴素DP秒出。然后单调队列优化因为没接触过所以不会emmm
而且脑补没补出来
坐等四月省选倒数第一emmm
心态爆炸,偷懒放题解链接
#include<cstdio> #include<cstring> #include<cctype> #include<cstdlib> #include<algorithm> #define maxn 2020 #define INF 0x7fffffff using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int f[maxn][maxn]; struct Day{ int vali,valo,numi,numo; }q[maxn]; struct File{ int que[maxn*2],h,t; File(){h=1;t=0;} void clear(){h=1;t=0;} }s; int ans; int main(){ memset(f,-127/3,sizeof(f)); int n=read(),m=read(),w=read(); for(int i=1;i<=n;++i) q[i]=(Day){read(),read(),read(),read()}; for(int i=1;i<=n;++i) f[i][0]=0; for(int i=1;i<=n;++i){ for(int j=0;j<=q[i].numi;++j) f[i][j]=max(f[i-1][j],-j*q[i].vali); for(int j=m;j>=0;--j) f[i][j]=max(f[i][j],f[i-1][j]); if(i-w-1<0) continue; int last=i-w-1; s.clear(); for(int j=0;j<=m;++j){ while(s.h<=s.t&&s.que[s.h]<j-q[i].numi) s.h++; while(s.h<=s.t&&f[last][s.que[s.t]]+s.que[s.t]*q[i].vali<=f[last][j]+j*q[i].vali) s.t--; s.que[++s.t]=j; f[i][j]=max(f[i][j],f[last][s.que[s.h]]-q[i].vali*(j-s.que[s.h])); } s.clear(); for(int j=m;j>=0;--j){ while(s.h<=s.t&&s.que[s.h]>j+q[i].numo) s.h++; while(s.h<=s.t&&f[last][j]+q[i].valo*j>=f[last][s.que[s.t]]+s.que[s.t]*q[i].valo) s.t--; s.que[++s.t]=j; f[i][j]=max(f[i][j],f[last][s.que[s.h]]+q[i].valo*(s.que[s.h]-j)); } } for(int i=0;i<=m;++i) ans=max(ans,f[n][i]); printf("%d",ans); return 0; }