十分普通的DP+不平凡的转移

传送门

这道题状态十分明显。转移是\(O(n^4)\)的,过不去,我们需要优化。

一个十分显然的DP是\(f(i,j)\)表示第\(i\)天时候拥有\(j\)单位股票的最大收益。(可以小于零)。它的转移方式是:

\(f(i,j)=max(f(k,b)+(b-j) \times sell[t] or(buy[t]))\)

此时,我们发现一个转移需要两重循环,也就是\(O(n^2)\),加上右边的式子,就是\(O(n^4)\)的。

考虑优化:

  • 对于转移方程,发现我们可以进行参变量分离。对状态转移方程进行代数变形。

    • \(RHS=max(f(k,b)+b \times sell[t]-j \times sell[t])\)
    • \(j\)在转移时,是最开始那个等式的\(LHS\),可以提前确定,从\(max\)拿出来。
    • \(RHS=max(f(k,b)+b \times sell[t])-j\times sell[t]\)
    • 于是,对于\(max(f(k,b)+b \times sell[t])\),可以拿数据结构维护了。
  • 对于转移方法,我们只需要从\(f(i-W-1,j) , j\le maxP\)转移过来就好了。这一定是最优的那个状态,比它要早的状态一定会$\le f(i-W-1,j) $。

    • 因为这个(晚的)状态在转移的时候,考虑过 从比他 (早的) 状态直接转移过来,于是\(f(i-W-1,j)\)不小于前面那个。

于是,我们可以将\(f(i-W-1,b) ,b\le maxP\)的所有状态压入某个数据结构。我们发现,对于这种数据结构的要求是:

  • 维护最大值
  • 可以清理过期状态(买入卖出股票有多少限制)
  • 重置方便

就是单调队列吃饭的本领。

一句话解释单调队列:一个状态比你小(限制条件少)还比你强(数值大),那么你就被淘汰了。

单调队列是\(O(n)\)的,枚举\(LHS\)的\(i\)是\(O(n)\)的。总复杂度\(O(n^2)\),可以过了。


  1. #include<iostream>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<bitset>
  7. #include<vector>
  8. #include<map>
  9. #include<ctime>
  10. #include<cstdlib>
  11. #include<set>
  12. #include<bitset>
  13. #include<stack>
  14. #include<list>
  15. #include<cmath>
  16. using namespace std;
  17. #define RP(t,a,b) for(register ll (t)=(a),edd_=(b);t<=edd_;++t)
  18. #define DRP(t,a,b) for(register ll (t)=(a),edd_=(b);t>=edd_;--t)
  19. #define ERP(t,a) for(int t=head[a];t;t=e[t].to)
  20. #define Min(a,b) ((a)<(b)?(a):(b))
  21. #define TMP template<class ccf>
  22. typedef long long ll;
  23. TMP inline ccf qr(ccf k){
  24. char c=getchar();
  25. ccf x=0;
  26. int q=1;
  27. while(c<48||c>57)
  28. q=c==45?-1:q,c=getchar();
  29. while(c>=48&&c<=57)
  30. x=x*10+c-48,c=getchar();
  31. if(q==-1)
  32. x=-x;
  33. return x;
  34. }
  35. const int maxn=2e3+15;
  36. inline void Swap(ll& a,ll& b){
  37. ll k=a;
  38. a=b;
  39. b=k;
  40. }
  41. ll buy[maxn];
  42. ll sell[maxn];
  43. ll buytimes[maxn];
  44. ll selltimes[maxn];
  45. ll n,maxP,W;
  46. ll dp[maxn][maxn];
  47. int q[maxn];
  48. TMP inline ccf Max(ccf a,ccf b){
  49. if(a<b)
  50. return b;
  51. return a;
  52. }
  53. inline void init(){
  54. memset(dp,-0xf,sizeof dp);
  55. RP(t,1,n){
  56. buy[t]=qr(1ll);
  57. sell[t]=qr(1ll);
  58. buytimes[t]=qr(1ll);
  59. selltimes[t]=qr(1ll);
  60. }
  61. RP(t,1,n){
  62. int head=1,tail=0;
  63. if(t-W-1>0){
  64. //trade
  65. DRP(i,maxP,0){
  66. while(head<=tail&&q[head]>i+selltimes[t])
  67. head++;
  68. while(head<=tail&&
  69. dp[t-W-1][q[tail]]+1ll*q[tail]*sell[t]
  70. <=dp[t-W-1][i]+1ll*i*sell[t]
  71. )
  72. --tail;
  73. q[++tail]=i;
  74. if(head<=tail)
  75. dp[t][i]=max(dp[t][i],dp[t-W-1][q[head]]+(q[head]-i)*sell[t]*1ll);
  76. }
  77. //purchase
  78. head=1,tail=0;
  79. RP(i,0,maxP){
  80. while(head<=tail&&q[head]<i-buytimes[t])
  81. ++head;
  82. while(head<=tail&&
  83. dp[t-W-1][q[tail]]+q[tail]*buy[t]
  84. <=dp[t-W-1][i]+i*buy[t])
  85. --tail;
  86. q[++tail]=i;
  87. if(head<=tail)
  88. dp[t][i]=Max(dp[t][i],dp[t-W-1][q[head]]+(q[head]-i)*buy[t]*1ll);
  89. }
  90. }
  91. //restart
  92. RP(i,0,maxP){
  93. dp[t][i]=Max(dp[t][i],dp[t-1][i]);
  94. if(i<=buytimes[t])
  95. dp[t][i]=Max(dp[t][i],-i*buy[t]);
  96. }
  97. }
  98. ll ans=0;
  99. RP(t,0,maxP)
  100. ans=max(ans,dp[n][t]);
  101. cout<<ans<<endl;
  102. }
  103. int main(){
  104. #ifndef ONLINE_JUDGE
  105. freopen("in.in","r",stdin);
  106. freopen("out.out","w",stdout);
  107. #endif
  108. while(~scanf("%lld%lld%lld",&n,&maxP,&W))
  109. init();
  110. return 0;
  111. }

【题解】[SCOI2010]股票交易的更多相关文章

  1. 【BZOJ1855】[Scoi2010]股票交易 DP+单调队列

    [BZOJ1855][Scoi2010]股票交易 Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预 ...

  2. [luogu] P2569 [SCOI2010]股票交易 (单调队列优化)

    P2569 [SCOI2010]股票交易 题目描述 最近 \(\text{lxhgww}\) 又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,\(\te ...

  3. 单调队列优化DP || [SCOI2010]股票交易 || BZOJ 1855 || Luogu P2569

    题面:P2569 [SCOI2010]股票交易 题解: F[i][j]表示前i天,目前手中有j股的最大收入Case 1:第i天是第一次购买股票F[i][j]=-j*AP[i]; (1<=j< ...

  4. 1855: [Scoi2010]股票交易[单调队列优化DP]

    1855: [Scoi2010]股票交易 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1083  Solved: 519[Submit][Status] ...

  5. 洛谷P2569 [SCOI2010]股票交易

    P2569 [SCOI2010]股票交易 题目描述 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股 ...

  6. BZOJ 1855: [Scoi2010]股票交易(DP+单调队列)

    1855: [Scoi2010]股票交易 Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未 ...

  7. [SCOI2010]股票交易(单调队列优化dp)

    [SCOI2010]股票交易 题目描述 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第 ...

  8. [bzoj1855][Scoi2010]股票交易_动态规划_单调队列

    股票交易 bzoj-1855 Scoi-2010 题目大意:说不明白题意系列++...题目链接 注释:略. 想法:这个题还是挺难的. 动态规划没跑了 状态:dp[i][j]表示第i天手里有j个股票的最 ...

  9. bzoj1855: [Scoi2010]股票交易

    Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价 ...

随机推荐

  1. luogu P3092 [USACO13NOV]没有找零No Change

    题目描述 Farmer John is at the market to purchase supplies for his farm. He has in his pocket K coins (1 ...

  2. 某考试T1 game

    题目背景 无 题目描述 Alice 和 Bob 在一个圆环上玩游戏.圆环上有 n 个位置,按照顺时针顺序 依次标号为 1 到 n.Alice 和 Bob 分别有一个数字集合,集合中都是在 [1, n− ...

  3. Eclipse的调试功能(转)(让Eclipse也能有VS的即时窗口那样的即时代码调试功能)

    前言:可以很明确的说明,eclipse也有像vs那样的即时窗口来运行即时代码的功能. 调试的界面如下: 如果要像vs那样的即时调试功能,需要做一些设置,就是Expressions功能. 开通步骤:Wi ...

  4. python遍历当前目录并删除某文件

    #coding: utf-8 """ this programe is to clear driverlog below this dir __author__:the_ ...

  5. 从头认识java-14.2 进一步了解数组

    这一章节我们来全面了解一下数组. 1.数组在初始化之前.我们不能使用他的引用来做不论什么事情. package com.ray.ch14; public class Test { public sta ...

  6. CentOS SVN 服务器搭建

    源码目录:/home/user/project 工程名:project 工程目录:/source/svn/project 访问地址:svn://ip/project 一. 安装svn yum inst ...

  7. pymongo的基本使用

    #!/usr/bin/env python # -*- coding:utf-8 -*- """ MongoDB存储 在这里我们来看一下Python3下MongoDB的存 ...

  8. maximal-rectangle——找出最大矩形的面积

    Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and ...

  9. swoole新手教程01-环境搭建及扩展安装

    写在前面的废话 <swoole源代码分析>已经写了13章,整个swoole的核心架构基本都分析的差点儿相同了.于是心里一直以来想整理swoole的文档并写一份教程的想法就再度浮了出来. 实 ...

  10. Oracle 修改带数据的字段类型

    http://www.cnblogs.com/LDaqiang/articles/1157998.html由于需求变动,现要将一个类型NUMBER(8,2)的字段类型改为 char.大体思路如下:   ...