csu 1085: 挖宝藏
/* 简单dp加单调队列 */ #include<stdio.h> #include<string.h> int N,M,D,S; int ac[6000]; int dp[2][6000]; int qu[6000]; void fc() { int i,k,j,l,cnt; for(i=0;i<M;i++) { cnt=i%2; qu[0]=1; k=0;j=0; for(l=1;l<=N;l++) { while(k<=j&&dp[cnt][qu[j]]<=dp[cnt][l]) j--; dx qu[++j]=l; while((qu[j]-qu[k])>(2*D)) k++; if(l>D) dp[cnt^1][l-D]=dp[cnt][qu[k]]; } for(l=N+1;(l-D)<=N;l++) { while(qu[k]<(l-2*D)) k++; dp[cnt^1][l-D]=dp[cnt][qu[k]]; } for(l=1;l<=N;l++) dp[cnt^1][l]+=ac[l]; } cnt=M%2; int max=-1; for(i=1;i<=N;i++) if(dp[cnt][i]>max) max=dp[cnt][i]; printf("%d\n",max); } int main() { int i,max; while(scanf("%d %d %d %d",&N,&M,&D,&S)!=EOF) { max=0; for(i=1;i<=N;i++) { scanf("%d",&ac[i]); if(ac[i]>max) max=ac[i]; } if((D+1)>=N) printf("%d\n",M*max+ac[S]); else { for(i=0;i<=N;i++) dp[0][i]=dp[1][i]=-1000000000; dp[0][S]=ac[S]; fc(); } } return 0; }