前言

感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新。主要做一个收集整理总结工作。

记录

0x01

POJ - 1821 Fence,比较适合入门的题,写出转移方程后可以比较容易的看出决策变量的取值范围的界是单调变化的,以及价值拆开之后也是单调的

#include<iostream>
#include<cstdio>
#include<algorithm>
#define dd(x) cout<<#x<<" = "<<x<<" "
#define de(x) cout<<#x<<" = "<<x<<"\n"
#define sz(x) int(x.size())
#define All(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
const int maxn=2e4+10,mod=1e9+7,INF=0x3f3f3f3f;
struct node
{
int l,p,s;
}a[maxn];
bool cmp(node x,node y)
{
return x.s<y.s;
}
int q[maxn],h,t;
ll f[105][maxn];
inline ll val(int i,int k)
{
return f[i-1][k]-k*a[i].p;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for (int i=1;i<=k;++i)
scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
sort(a+1,a+k+1,cmp);
for (int i=1;i<=k;++i)
{
h=0,t=-1;
for (int k=max(0,a[i].s-a[i].l);k<a[i].s;++k)
{
while (h<=t&&val(i,k)>=val(i,q[t]))
--t;
q[++t]=k;
}
for (int j=1;j<=n;++j)
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
if (j<a[i].s)
continue;
while (h<=t&&q[h]<j-a[i].l)
++h;
if (h<=t)
f[i][j]=max(f[i][j],val(i,q[h])+j*a[i].p);
}
}
cout<<f[k][n];
return 0;
}

0x02

HDU 3401 trade,被不少博客当做单调队列优化DP的入门题,但我感觉这题要考虑的细节挺多的,并不简单。定义状态f(i,j)为第i天拥有j数量股票的最大收益,转移的思路就是根据不作为、买和卖三种操作来转移。转移时,卖和买操作中对于股票数的枚举用单调队列来优化掉,然后可以注意到我们是不需要枚举第几天来转移的(由于允许某天中不作为,这种操作的存在显然使得有f(i,j)>=f(i-1,j),即天数的增加只可能使收益变大,而不可能更糟),因此直接用i-w-1来转移就好了。因此总复杂度为平方级别,即枚举i,j的复杂度。细节见代码注释。

#include<bits/stdc++.h>
#define dd(x) cout<<#x<<" = "<<x<<" "
#define de(x) cout<<#x<<" = "<<x<<endl
#define sz(x) int(x.size())
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define All(x) x.begin(),x.end()
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef priority_queue<int> BQ;
typedef priority_queue<int,vector<int>,greater<int> > SQ;
const int maxn=2e3+10,INF=0x3f3f3f3f,mod=1e9+7;
int ap[maxn],bp[maxn],as[maxn],bs[maxn],f[maxn][maxn],q[maxn],h,t;
int main()
{
int T;
cin>>T;
while (T--)
{
int n,maxp,w;
scanf("%d%d%d",&n,&maxp,&w);
for (int i=1;i<=n;++i)
scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
for (int i=0;i<=n;++i)
for (int j=0;j<=maxp;++j)
f[i][j]=-INF;
for (int i=1;i<=n;++i)
{
if (i<=w+1) // 注意:当前日期i小于w+1时,若拥有j数量的股票,一定是当天或者前面的某天购买来的,因此如下更新
{
for (int j=0;j<=maxp;++j)
{
if (j<=as[i])
f[i][j]=-ap[i]*j;
f[i][j]=max(f[i][j],f[i-1][j]);
}
}
else
{
// 不作为
for (int j=0;j<=maxp;++j)
f[i][j]=max(f[i][j],f[i-1][j]);
// 买
h=t=0;
q[0]=0;
for (int j=1;j<=maxp;++j)
{
while (h<=t&&j-q[h]>as[i])
++h;
f[i][j]=max(f[i][j],f[i-w-1][q[h]]-(j-q[h])*ap[i]);
while (h<=t&&f[i-w-1][j]+j*ap[i]>=f[i-w-1][q[t]]+q[t]*ap[i])
--t;
q[++t]=j;
}
// 卖
h=t=0;
q[0]=maxp;
for (int j=maxp-1;j>=0;--j)
{
while (h<=t&&q[h]-j>bs[i])
++h;
f[i][j]=max(f[i][j],f[i-w-1][q[h]]+(q[h]-j)*bp[i]);
while (h<=t&&f[i-w-1][j]+j*bp[i]>=f[i-w-1][q[t]]+q[t]*bp[i])
--t;
q[++t]=j;
}
}
}
int ans=-INF;
for (int i=0;i<=maxp;++i)
ans=max(ans,f[n][i]);
printf("%d\n",ans);
}
return 0;
}

单调队列优化DP——习题收集的更多相关文章

  1. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

  2. 单调队列优化dp

    洛谷p3800(单调队列优化DP) 题目背景 据说在红雾异变时,博丽灵梦单身前往红魔馆,用十分强硬的手段将事件解决了. 然而当时灵梦在Power达到MAX之前,不具有“上线收点”的能力,所以她想要知道 ...

  3. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

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

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

  5. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

  6. Parade(单调队列优化dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    ...

  7. BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP

    BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...

  8. 【单调队列优化dp】 分组

    [单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...

  9. [小明打联盟][斜率/单调队列 优化dp][背包]

    链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...

随机推荐

  1. golang glog

    原文链接:https://blog.csdn.net/u010857876/article/details/79094942 Flush log 产生后,会暂存在内存的buffer中.只有显示的调用 ...

  2. 怎样启动和关闭nginx服务器

    启动: 直接使用命令: nginx nginx 关闭1: 快速停止 nginx -s stop 关闭2: 完整有序停止 nginx -s quit 重启: 如下 nginx -s reload

  3. hexo发布后样式丢失

    修改配置中url路径,和root,问题解决.

  4. 【转】在 Delphi 中创建 Linux 守护程序(服务进程)

    转自波哥的译文,必须转过来,太有价值了!原文地址在这里.以下为原文内容: 本文译自 原文链接,语言上做了精炼和排版的变更,以便更简洁明了. Delphi 开始支持 Linux 平台为 Delphi 开 ...

  5. Windows Phone惨遭微软放弃

    微软在电脑操作系统上的用户保有量一直处于遥遥领先的地位,特别是最新的Windows 10系统,一经推出,市场表现就比较好,但相比起来,微软的手机操作系统Windows Phone就被贴上“差等生”的标 ...

  6. asp.net 身份验证(Update)

    ASP.NET   有四种 身份验证, 用的最广的就是 Froms   这几天 做项目    想用到 配置文件, 比较了 MVC 和ASP.NET  发现 还是 MVC 给力(MVC 叫做 过滤器  ...

  7. 009.增删查改语法(sql实例)

    --------------------------------------------合并结果集SELECT UNION -------------------------------------- ...

  8. 用实例的方式去理解storm的并发度

    什么是storm的并发度 一个topology(拓扑)在storm集群上最总是以executor和task的形式运行在suppervisor管理的worker节点上.而worker进程都是运行在jvm ...

  9. npm 安装指定版本的包

    使用 包名@版本号 指定, 例如,安装 Express 3.21.2, $ npm

  10. Java抽象类 详解

    一.抽象类的基本概念 普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法.普通方法.static方法.常量和变量等内容.而抽象类是指在普通类的结构里面增加抽象方法的组成 ...