代码改变世界

[SCOI2010]股票交易

2019-06-17 16:12  一只弱鸡丶  阅读(236)  评论(0编辑  收藏  举报

传送门:

#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
#define ll long long
#define re register
const int N=1e6+10;
inline void read(int &a)
{
    a=0;
    int d=1;
    char ch;
    while(ch=getchar(),ch>'9'||ch<'0')
        if(ch=='-')
            d=-1;
    a=ch^48;
    while(ch=getchar(),ch>='0'&&ch<='9')
        a=(a<<3)+(a<<1)+(ch^48);
    a*=d;
}
int f[2005][2005],q[2005];///第一维天数,第二维持有股数
int main()
{
    int n,m,w;
    read(n);
    read(m);
    read(w);
    memset(f,128,sizeof(f));
    for(re int i=1;i<=n;i++)
    {
        int ap,bp,as,bs;
        read(ap),read(bp),read(as),read(bs);
        for(re int j=0;j<=m&&j<=as;j++)
            f[i][j]=-j*ap;///无股买入
        for(re int j=0;j<=m;j++)
            f[i][j]=max(f[i][j],f[i-1][j]);///不买不卖
        if(i>w)///有股买入+卖出,因为一次交易后有w天不能交易,所以i>w才能做
        {
            int h,t;
            h=1,t=1;
            for(re int j=0;j<=m;j++)
            {
                while(h<t&&q[h]<j-as)
                    h++;
                while(h<t&&f[i-w-1][q[t-1]]+q[t-1]*ap<=f[i-w-1][j]+j*ap)
                    t--;
                q[t++]=j;
                if(h<t)
                    f[i][j]=max(f[i][j],f[i-w-1][q[h]]+q[h]*ap-j*ap);
            }
            h=1,t=1;
            for(re int j=m;j>=0;j--)
            {
                while(h<t&&q[h]>j+bs)
                    h++;
                while(h<t&&f[i-w-1][q[t-1]]+q[t-1]*bp<=f[i-w-1][j]+j*bp)
                    t--;
                q[t++]=j;
                if(h<t)
                    f[i][j]=max(f[i][j],f[i-w-1][q[h]]+q[h]*bp-j*bp);
            }
        }
    }
    printf("%d",f[n][0]);
    return 0;
}