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;
}

 

posted @ 2012-07-25 12:02  zhuiy  阅读(131)  评论(0编辑  收藏  举报