单调队列优化DP——习题收集
前言
感觉可以用单调队列优化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——习题收集的更多相关文章
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
- 单调队列优化dp
洛谷p3800(单调队列优化DP) 题目背景 据说在红雾异变时,博丽灵梦单身前往红魔馆,用十分强硬的手段将事件解决了. 然而当时灵梦在Power达到MAX之前,不具有“上线收点”的能力,所以她想要知道 ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- 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 ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 【单调队列优化dp】 分组
[单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...
- [小明打联盟][斜率/单调队列 优化dp][背包]
链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...
随机推荐
- python爬取信息并保存至csv
import csv import requests from bs4 import BeautifulSoup res=requests.get('http://books.toscrape.com ...
- 由[].slice.call()引发的思考
由[].slice.call()引发的思考 经常看到大家用[].slice.call()或者Array.prototype.slice.call(): 我一直是一知半解的,今天算是基本弄清楚了, ...
- 使用 FTP 迁移 SQL Server 数据_迁移数据_快速入门(SQL Server)_云数据库 RDS 版-阿里云
背景信息 阿里云数据库 SQL Server 版导入数据有如下限制: 仅支持导入 SQL Server 2005.SQL Server 2008.SQL Server 2008R2 版本数据 仅支持全 ...
- 重拾MVC——第二天:Vue学习与即时密码格式验证
今天是复习MVC的第二天,准备自己写一个后台管理,然后慢慢写大,做全. 个人感觉做 Web 的,前端知识是必备的,所有今天学习了一下 Vue,很多人用这个,我以前没有用过,今天把它补起来. 比较了各个 ...
- netstat用法详解
netstat用法详解 知识,netstat用法详解 图片 netstat用法详解 内容,netstat用法详介绍,netstat用法详正文 netstat命令是一个监控TCP/IP网络的非常有用的工 ...
- selenium无头浏览器&规避操作
一.无头浏览器概述: 无头浏览器主要目的是打开浏览器但用户看不到 简单用法如下: from selenium import webdriver from time import sleep from ...
- Lab1 Report
Lab1 report A) The brief description that you install junit, hamcrest and eclemma. a) install junit ...
- Junit5常用注解
0. IDEA中Maven项目测试类的新建方法 a. 如图在src目录下新建文件夹test b. 鼠标右键test,将该文件设置成test source c. 右键需要新建的测试类,如下图操作,选中T ...
- Linux克隆修改配置文件及IP
Linux下安装基本的开发软件比较费劲,特别是安装mysql的时候,这时候就需要学会克隆及直接备份base虚拟机了,下次直接打开,修改网卡文件信息就完事. 克隆虚拟机eth0网卡出现的问题解决1:修改 ...
- linux安装vsftpd后无法登陆
安装完成后在主机上登陆时,不管是输入用户,还是匿名都无法登陆 经过检查,发现是因为/etc/hosts.deny禁止了所有ip访问 将hosts.deny中的all:all删除,或者在/etc/hos ...