十分普通的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<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<bitset>
#include<vector>
#include<map>
#include<ctime>
#include<cstdlib>
#include<set>
#include<bitset>
#include<stack>
#include<list>
#include<cmath>
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<class ccf>
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<b)
return b;
return a;
} inline void init(){
memset(dp,-0xf,sizeof dp);
RP(t,1,n){
buy[t]=qr(1ll);
sell[t]=qr(1ll);
buytimes[t]=qr(1ll);
selltimes[t]=qr(1ll);
}
RP(t,1,n){
int head=1,tail=0;
if(t-W-1>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]<i-buytimes[t])
++head;
while(head<=tail&&
dp[t-W-1][q[tail]]+q[tail]*buy[t]
<=dp[t-W-1][i]+i*buy[t])
--tail;
q[++tail]=i;
if(head<=tail)
dp[t][i]=Max(dp[t][i],dp[t-W-1][q[head]]+(q[head]-i)*buy[t]*1ll);
}
} //restart
RP(i,0,maxP){
dp[t][i]=Max(dp[t][i],dp[t-1][i]);
if(i<=buytimes[t])
dp[t][i]=Max(dp[t][i],-i*buy[t]);
} }
ll ans=0;
RP(t,0,maxP)
ans=max(ans,dp[n][t]);
cout<<ans<<endl; } int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
while(~scanf("%lld%lld%lld",&n,&maxP,&W))
init();
return 0;
}

【题解】[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. SDOI 2015 约束个数和

    Description: 共\(T \le 5 \times 10^4\)组询问, 每组询问给定\(n\)和\(m\), 请你求出 \[ \sum_{i = 1}^n \sum_{j = 1}^m \ ...

  2. ssh免秘钥登陆实现

    1.用处 搭建集群或者工作中登陆跳板机经常需要做免秘钥互相登陆彼此服务器. 2. 准备工作   假设A主机10.20.0.1想通过ssh登录到B主机10.20.0.2上.   那么客户端(A主机)需要 ...

  3. iOS网络交互数据格式解析之json

    作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式.从ios5开 始,apple提供了对json的原生支持,但为了兼容以前的ios版本,我们仍然需要使用第三方库来解析常用 ...

  4. 【hibernate】Hibernate SQL 方言(hibernate.dialect)

    参考如下: RDBMS Dialect DB2 org.hibernate.dialect.DB2Dialect DB2 AS/400 org.hibernate.dialect.DB2400Dial ...

  5. TypeError at /post/ render_to_response() got an unexpected keyword argument 'context_instance'

    Exception Type: TypeError at /post/ Exception Value: render_to_response() got an unexpected keyword ...

  6. mac 下bash命令

    可以一行写一条命令 nginx uwsgi /Users/***/djangoprojects/bpmTest/uwsgi.ini 将上述命令保存成**.sh文件 这样,然后bash ***.sh 实 ...

  7. k8s学习(一)——kubectl与api-server之间的交互核心过程

    k8s的架构是用户使用kubectl工具对虚拟机资源进行各种各样的控制和定制. 而kubectl本身并不包含对其核心资源的访问与控制.而是通过http通信与api-server进行交互实现资源的管理. ...

  8. 性能测试报告模板 V1.0

    1. 测试项目概述与测试目的 1.1 项目概述 本部分主要是针对即将进行压力测试的对象(接口.模块.进程或系统)进行概要的说明,让人明白该测试对象的主要功能与作用及相关背景. 1.2 测试目标 简要列 ...

  9. mysql数据库解决中文乱码问题

    安装mysql之后.假设存储中文.再读出的时候就会出现乱码问题. 如今的字符集有几百种之多,都是一些公司或者组织定义的. 我们应该使用可以容纳世界所有语言所有字符的字符集,这样就不会再出现乱码问题. ...

  10. linux虚拟机上挂载U盘

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTQwMjU5Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...