前言

感觉可以用单调队列优化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. 怎样创建一个独立于当前文档的新的Document对象

    使用: document.implementation. 如下所示, 新创建的Document对象可以正常使用相关属性和方法, 然后将它的根节点与当前文档的根节点做一个替换. var doc = do ...

  2. select into from与insert into select区别

    创建一个table2  向table2中插入 table1中name为11的所有行(前提table2不存在) select * into table2 from table1 where name=‘ ...

  3. luogu题解 P3763 【[TJOI2017]DNA】

    题目链接: https://www.luogu.org/problemnew/show/P3763 思路: 首先我们要用到Rabin-Karp哈希,其实就是这个: 若\(w_{str}\)=(\(a_ ...

  4. mysql5.7 密码字段名更改

    由password更改为authentication_string update user set authentication_string=password("123456") ...

  5. IOS 改变UISearchBar的背景色

    之前网上提供的方法试了很多种  都不能很好的去掉背景色  ,修改背景色方法如下: searchbar.barStyle = UIBarStyleBlackTranslucent; searchbar. ...

  6. python中括号知识点

    Python语言中括号分为几个类型,常见的三个圆括号是圆括号().中间圆括号[]和大括号.它的函数也不同,代表不同的Python基本内置数据类型. python括号 python()中的括号:表示tu ...

  7. easyUi 的form和validate组件

    以下代码不能运行,只是我在学习过程中记录的笔记,但代码可以用!!! 可以按照需要截取. <%@ page language="java" contentType=" ...

  8. RobHess的SIFT代码解析之RANSAC

    平台:win10 x64 +VS 2015专业版 +opencv-2.4.11 + gtk_-bundle_2.24.10_win32 主要参考:1.代码:RobHess的SIFT源码:SIFT+KD ...

  9. 微信小程序开发(十一)获取手机的完整详细信息

    // succ.wxml <view style='position:absolute; top:30%; left:35%;font-size:36rpx'>{{name}}:签到成功. ...

  10. CSP2019 退役记

    本来想写"退役在即"的,考完 Day2 后直接改成"退役记"了 Day 0 在 ssf 的机房里继续变弱,自己写了一遍 splay 板子,居然写对了,开心 非常 ...