普及组T4
还有点不懂的先咕着
#include<bits/stdc++.h> using namespace std; const int maxn=1009; int n,m,p,ans=-1e9; int sum[maxn][maxn],gd[maxn][maxn],cs[maxn],rec[maxn][maxn];//rec[i][j]=f[i]-sum[i][j]-cost[j] int pre[maxn][maxn],f[maxn]; struct node{ int x,st;//rec值和时间 node(){} node(int xx,int tt){ x=xx;st=tt; } bool operator <(const node&t)const{ return x<t.x; } }; priority_queue<node>q[maxn]; void upd(int s,int now){ node tmp=q[s].top(); while(now-tmp.st>=p){ q[s].pop(); tmp=q[s].top(); } } int main(){ scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&gd[i%n][j]); for(int i=0;i<n;i++)scanf("%d",&cs[i]); for(int i=1;i<=m;i++){ for(int j=0;j<n;j++) sum[i][j]=sum[i-1][(j-1+n)%n]+gd[j][i]; } for(int i=0;i<n;i++)pre[0][(i-1+n)%n]=i;//储存起始点,用于判断属于哪个队列 for(int i=0;i<n;i++){ rec[0][i]=-cs[i]; q[pre[0][i]].push(node(-cs[i],0)); } memset(f,~0x3f,sizeof(f)); for(int i=1;i<=m;i++){ int tmp=-1e9; for(int j=0;j<n;j++){//更新答案以及上一阶段的最优值 f[i]=max(f[i],rec[i-1][(j-1+n)%n]+sum[i][j]); ans=max(ans,f[i]); tmp=max(tmp,f[i]); } for(int j=0;j<n;j++){ pre[i][j]=pre[i-1][(j-1+n)%n]; q[pre[i][j]].push(node(tmp-sum[i][j]-cs[j],i)); while(i-q[pre[i][j]].top().st>=p)q[pre[i][j]].pop();//排除过时决策,i递增所以正确 rec[i][j]=q[pre[i][j]].top().x; } } printf("%d",ans); }