luogu 2569 股票交易 单调队列dp

注意转移方程

分1.凭空买 2.不买不卖 3.在原来基础上买 4.在原来基础上卖 四种情况

head=1,tail=0;再判断一下head<=tail也可以

#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int n,m,w,ans;
int ap[N],bp[N],as[N],bs[N];
int f[N][N];
int q[10000],head=1,tail=0;
int main()
{
    scanf("%d%d%d",&n,&m,&w);
    for(int i=1;i<=n;i++)
    scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
    
    memset(f,128,sizeof f);
    for(int i=0;i<=n;i++) f[i][0]=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=as[i];j++) f[i][j]=-ap[i]*j;
        for(int j=m;j>=0;j--) f[i][j]=max(f[i][j],f[i-1][j]);
        if(i-w-1>=0)
        {
            head=1;tail=0;
            for(int j=0;j<=m;j++)
            {
                while(head<=tail&&q[head]<j-as[i]) head++;
                if(head<=tail) f[i][j]=max(f[i][j],f[i-w-1][q[head]]-ap[i]*(j-q[head])); 
                while(head<=tail&&f[i-w-1][j]+ap[i]*j>=f[i-w-1][q[tail]]+ap[i]*q[tail]) tail--;
                q[++tail]=j;
                
            } 
            head=1;tail=0;
            for(int j=m;j>=0;j--)
            {
                while(head<=tail&&q[head]>j+bs[i]) head++;
                if(head<=tail) f[i][j]=max(f[i][j],f[i-w-1][q[head]]+bp[i]*(q[head]-j));
                while(head<=tail&&f[i-w-1][j]+bp[i]*j>=f[i-w-1][q[tail]]+bp[i]*q[tail]) tail--;
                q[++tail]=j;
                
            } 
        } 
    }
    for(int i=0;i<=m;i++) ans=max(f[n][i],ans);
    printf("%d",ans);return 0;
}

猜你喜欢

转载自www.cnblogs.com/asdic/p/9693851.html