【題解】洛谷P4853[非酋yyf的sif之旅]B.yyf hates choukapai 單調佇列優化DP
阿新 • • 發佈:2018-12-13
#include<cstdio> const int M=8e4+5,C=3e3+5,N=45,S=N*C+M; int a[S],b[S],n,m,c,d,sum,hd[N],tl[N],s,q[N][S][2],f[S][N],p[S][N],pos[N],ans,Pos; //f[i][j]前i張牌連抽j次 p[i][j]記錄f[i][j]由哪個i轉移過來 int main() { //freopen("in.txt","r",stdin); scanf("%d%d%d%d",&n,&m,&c,&d);s=n*c+m; for(int i=1;i<=s;i++) scanf("%d",&a[i]),sum+=a[i]; for(int i=2;i<=c;i++) b[1]+=a[i]; for(int i=2;i<=s-c+1;i++) b[i]=b[i-1]-a[i]+a[i+c-1];//b[i]維護a[i+1]加到a[i+c-1] for(int i=1;i<=n;i++) hd[i]=1; for(int i=1;i<=s-c+1;i++) { if(i<=c){f[i][1]=b[i];continue;} for(int j=(i+c-2)/(c+d)+1;j<=(i+c-1)/c&&j<=n;j++) { if(hd[j-1]<=tl[j-1]&&q[j-1][hd[j-1]][1]<i-c-d)//隊頭超出範圍的出隊 hd[j-1]++; if(j-1>=(i-2)/(c+d)+1&&j-1<=(i-1)/c) {//能入隊的入隊 while(hd[j-1]<=tl[j-1]&&q[j-1][tl[j-1]][0]>=f[i-c][j-1]) tl[j-1]--; q[j-1][++tl[j-1]][0]=f[i-c][j-1];//0記錄的最大值 q[j-1][tl[j-1]][1]=i-c;//1記錄的位置 } f[i][j]=q[j-1][hd[j-1]][0]+b[i]; p[i][j]=q[j-1][hd[j-1]][1]; if(i>=s-c+1-d&&j==n&&ans<sum-f[i][j]) ans=sum-f[i][j],Pos=i; } } printf("%d\n",ans); for(int j=n;j;j--) pos[j]=Pos,Pos=p[Pos][j]; for(int i=1;i<=n;i++) printf("%d ",pos[i]); puts(""); return 0; }
總結
當時好像是寫了個0分的DP還是啥的,心態直接炸了,T3也沒咋寫就放棄了。自己的心態還是得練練,畢竟以後寫不來的比賽題多了去了(笑) 自己動態規劃太菜,這種狀態轉移方程都毫無頭緒。狀態轉移方程出來單調佇列就顯而易見了。