DP/单调队列优化


  题解:http://www.cnblogs.com/jianglangcaijin/p/3799736.html

  令f[i][j]表示第 i 天结束后,手里剩下 j 股的最大利润,则有:

    \[  f[i][j]= \begin{cases} f[i-1][j] &   &{(不买不卖)}\\ f[i-w-1][k]-ap[i]*(j-k)&   &{ j-as[i] \leq k \leq j-1 (买入)}\\ f[i-w-1][k]+bp[i]*(k-j)&   &{ j+1 \leq k \leq j+bs[i] (卖出)} \end{cases} \]

  对于买入,我们将式子变形得到:

    $$ f[i][j]=f[i-w-1][k]+ap[i]*k-ap[i]*j $$

  我们知道单调队列优化可以将形如 $ f[i]=max/min \{ f[k] \}+g[i] $ 的式子中对k的枚举利用队列进行优化,这个式子中,"f[k]" 即是 $ f[i-w-1][k]+ap[i]*k $,“g[i]”即是 $ -ap[i]*j $,所以我们在枚举 j 的同时即可完成对k的维护(即每个f[i]都是一次单调队列优化下的DP)

  而卖出同理。

 /**************************************************************
Problem: 1855
User: Tunix
Language: C++
Result: Accepted
Time:380 ms
Memory:17068 kb
****************************************************************/ //BZOJ 1855
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*=sign;
}
const int N=,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/ struct node{
int x,y;
node(int _=,int __=):x(_),y(__){}
}q[N];
int f[N][N];
int main(){
#ifndef ONLINE_JUDGE
freopen("1855.in","r",stdin);
freopen("1855.out","w",stdout);
#endif
int n=getint(),m=getint(),w=getint();
F(i,,n) F(j,,m) f[i][j]=-INF;
int ans=,ap,bp,as,bs;
F(i,,n){
ap=getint(); bp=getint(); as=getint(); bs=getint();
F(j,,as) f[i][j]=-ap*j;
F(j,,m) f[i][j]=max(f[i][j],f[i-][j]);
int k=i-w-;
if (k>=){
int st=,ed=;
F(j,,m){
while(st<ed && q[st].x<j-as) st++;
while(st<ed && q[ed-].y<=f[k][j]+ap*j) ed--;
q[ed++]=node(j,f[k][j]+ap*j);
if (st<ed) f[i][j]=max(f[i][j],q[st].y-ap*j);
}
st=ed=;
D(j,m,){
while(st<ed && q[st].x>j+bs) st++;
while(st<ed && q[ed-].y<=f[k][j]+bp*j) ed--;
q[ed++]=node(j,f[k][j]+bp*j);
if (st<ed) f[i][j]=max(f[i][j],q[st].y-bp*j);
}
}
ans=max(ans,f[i][]);
}
printf("%d\n",ans);
return ;
}

最新文章

  1. 安装windows&#160;server&#160;2012&#160;r2&#160;的那点事儿
  2. javaweb局部刷新-ajax异步请求springMVC显示返回的jsp内容,代替iframe
  3. 部署wcf到IIS时的问题
  4. 爱上MVC~AuthorizeAttribute验证不通过如何停止当前上下文
  5. TYVJ1288 飘飘乎居士取能量块 -SilverN
  6. 360极速浏览器使用postman
  7. RTSP 协议分析
  8. Linux命令之乐--awk
  9. Swift 中使用Nimble 库进行单元测试
  10. CAS单点登录配置[2]:证书生成
  11. ffmepg命令行参数
  12. DataGrid( 数据表格) 组件[3]
  13. gallery 从最左边开始显示并且默认选中第一个
  14. lol盒子重点内容
  15. Python基础学习6---存储器
  16. Go 延迟函数 defer 详解
  17. 【状压dp】Bzoj2064 分裂
  18. 二、core abp 数据库迁移
  19. C# 响应微信发送的Token验证,文字、图文自动回复、请求客服对话.....
  20. pandas使用lambda判断元素是否为空或者None

热门文章

  1. Knockout.Js官网学习(click绑定)
  2. kettle的windows安装
  3. NodeManager起不来
  4. PHP-POSIX正则表达式函数
  5. php中iconv函数使用方法
  6. PHP session回收机制
  7. 【深入比较ThreadLocal模式与synchronized关键字】
  8. 开源web终端ssh解决方案-gateone简介
  9. PHP 简单实现MySQL数据搜索、添加数据功能 以设备管理为例
  10. linux C 管道