博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【题解】[SCOI2010]股票交易
阅读量:4947 次
发布时间:2019-06-11

本文共 2132 字,大约阅读时间需要 7 分钟。

十分普通的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)\),可以过了。


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;#define RP(t,a,b) for(register ll (t)=(a),edd_=(b);t<=edd_;++t)#define DRP(t,a,b) for(register ll (t)=(a),edd_=(b);t>=edd_;--t)#define ERP(t,a) for(int t=head[a];t;t=e[t].to)#define Min(a,b) ((a)<(b)?(a):(b))#define TMP template
typedef long long ll;TMP inline ccf qr(ccf k){ char c=getchar(); ccf x=0; int q=1; while(c<48||c>57) q=c==45?-1:q,c=getchar(); while(c>=48&&c<=57) x=x*10+c-48,c=getchar(); if(q==-1) x=-x; return x;}const int maxn=2e3+15;inline void Swap(ll& a,ll& b){ ll k=a; a=b; b=k;}ll buy[maxn];ll sell[maxn];ll buytimes[maxn];ll selltimes[maxn];ll n,maxP,W;ll dp[maxn][maxn];int q[maxn];TMP inline ccf Max(ccf a,ccf b){ if(a
0){ //trade DRP(i,maxP,0){ while(head<=tail&&q[head]>i+selltimes[t]) head++; while(head<=tail&& dp[t-W-1][q[tail]]+1ll*q[tail]*sell[t] <=dp[t-W-1][i]+1ll*i*sell[t] ) --tail; q[++tail]=i; if(head<=tail) dp[t][i]=max(dp[t][i],dp[t-W-1][q[head]]+(q[head]-i)*sell[t]*1ll); } //purchase head=1,tail=0; RP(i,0,maxP){ while(head<=tail&&q[head]

转载于:https://www.cnblogs.com/winlere/p/10307970.html

你可能感兴趣的文章
apache 添加 ssl_module
查看>>
java小技巧
查看>>
POJ 3204 Ikki's Story I - Road Reconstruction
查看>>
getQueryString
查看>>
Servlet文件上传和下载的复习
查看>>
JavaScript笔记——正则表达式
查看>>
iOS PushMebaby
查看>>
网页消息类
查看>>
【BZOJ】2959: 长跑(lct+缩点)(暂时弃坑)
查看>>
BZOJ3687: 简单题(dp+bitset)
查看>>
Vim常用又容易忘的命令
查看>>
cf1132G. Greedy Subsequences(线段树)
查看>>
P1577 切绳子
查看>>
3117 高精度乘法
查看>>
安装 php-gd
查看>>
OO第二次总结
查看>>
mybatis-01-基本流程
查看>>
【BZOJ1064】[Noi2008]假面舞会 DFS树
查看>>
日志信息中总是打印行号可能导致系统缓慢
查看>>
MyBatis中别名的设置
查看>>