• 题解【洛谷P2569】[SCOI2010]股票交易


    题面

    (dp_{i,j}) 表示前 (i) 天,现在手里有 (j) 股的最大收益。

    转移需要分情况讨论:

    • 这一天不进行任何交易,即 (dp_{i,j} = dp_{i - 1, j})
    • 这一天买股票:
      • 在之前没有买过股票的情况下买股票:(dp_{i,j}=-j imes AP_{i})(0le jle AS_i));
      • 在之前的基础上买:(dp_{i,j}=dp_{i-w-1,k}-(j-k) imes AP_i)(j-AS_ile kle j)((alpha))
    • 这一天卖股票:
      • 在之前的基础上卖:(dp_{i,j}=dp_{i-w-1,k}+(k-j) imes BP_i)(jle kle j+BS_i)((eta))

    前两种情况可以直接维护,而后两种情况暴力是 (mathcal O (T^2MaxP)) 的,考虑如何优化。

    先化简一下式子:

    • ((alpha)dp_{i,j}=dp_{i-w-1,k}+k imes AP_i-j imes AP_i(j-AS_ile kle j))
    • ((eta)dp_{i,j}=dp_{i-w-1,k}+k imes BP_i-j imes AP_i(jle kle j+BS_i))

    我们发现这两个式子中 (k) 的取值都是在一段区间中,于是滑动窗口维护区间最值,可以使用单调队列。

    这样我们就可以 AC 此题了。

    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    template <typename T>
    inline T gi()
    {
        T f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 2003, M = N << 1;
    
    int n, maxp, w;
    int ap[N], bp[N], as[N], bs[N];
    int dp[N][N];
    int q[N], hh, tt;
    
    int main()
    {
        //File("");
        n = gi <int> (), maxp = gi <int> (), w = gi <int> ();
        for (int i = 1; i <= n; i+=1) 
    	    ap[i] = gi <int> (), bp[i] = gi <int> (), as[i] = gi <int> (), bs[i] = gi <int> ();
    	memset(dp, 0xcf, sizeof dp);
    	for (int i = 1; i <= n; i+=1)
    	{
    		for (int j = 0; j <= as[i]; j+=1) 
    			dp[i][j] = -j * ap[i];
    		for (int j = 0; j <= maxp; j+=1) 
    			dp[i][j] = max(dp[i][j], dp[i - 1][j]);
    		if (i <= w) continue;
    		q[hh = tt = 1] = 0;
    		for (int j = 0; j <= maxp; j+=1)
    		{
    			while (hh <= tt && q[hh] < j - as[i]) ++hh;
    			while (hh <= tt && dp[i - w - 1][q[tt]] + q[tt] * ap[i] < dp[i - w - 1][j] + j * ap[i]) --tt;
    			q[++tt] = j;
    			if (hh <= tt) dp[i][j] = max(dp[i][j], dp[i - w - 1][q[hh]] + q[hh] * ap[i] - j * ap[i]);
    		}
    		q[hh = tt = 1] = maxp + 1;
    		for (int j = maxp; j >= 0; j-=1)
    		{
    			while (hh <= tt && q[hh] > j + bs[i]) ++hh;
    			while (hh <= tt && dp[i - w - 1][q[tt]] + q[tt] * bp[i] < dp[i - w - 1][j] + j * bp[i]) --tt;
    			q[++tt] = j;
    			if (hh <= tt) dp[i][j] = max(dp[i][j], dp[i - w - 1][q[hh]] + q[hh] * bp[i] - j * bp[i]);
    		}
    	}
    	printf("%d
    ", *max_element(dp[n], dp[n] + 1 + maxp));
        return 0;
    }
    
  • 相关阅读:
    Log4j中conversionPattern的含义
    log4j.xml写入数据库,只有SQL和参数,无其他信息
    windows下根据进程ID强制杀死进程
    github简单使用教程
    junit mockito
    获取oracle 随机数
    循环插入oracle 存储过程
    2.1. 创建GitHub账号
    oracle 复制表结构表数据
    命令模式
  • 原文地址:https://www.cnblogs.com/xsl19/p/13939063.html
Copyright © 2020-2023  润新知