DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)
前缀和优化
当DP过程中需要反复从一个求和式转移的话,可以先把它预处理一下。运算一般都要满足可减性。
比较naive就不展开了。
题目
【Todo】洛谷P2513 [HAOI2009]逆序对数列
【Done】洛谷P2511 [HAOI2008]木棍分割
【Done】洛谷P4099 [HEOI2013]SAO
【Done】NOIAC37 染色
单调队列优化
前置技能:单调队列(经典的问题模型:洛谷P1886 滑动窗口)
用于优化形如\(f_i=\min/\max_{j=l_i}^{i-1}\{g_j\}+w_i\),且满足\(l_i\le l_{i+1}\)的转移。
人话:对于序列中的每个点,从其左侧一段决策区间内的最值进行转移,且决策区间随着序列下标的增大也不断右移(就像窗口向右滑动)。
设\(j<k\),容易发现如果\(g_j\)劣于\(g_k\)的话,那么当决策区间移动到\(k\)以后,\(j\)永远不会成为最优决策点,再也不会被转移了。
于是,我们只要维护一个队列,满足下标递增,决策性递减。我们需要当前的队首成为最优决策点,那么当队首第一次超出了区间范围(以后也就永远超出了)就把它出队。为了保证单调性,队尾新加入点之前,要先把队列中比它劣的点依次从队尾出队。
题目
【Sol.】洛谷P1776 宝物筛选_NOI导刊2010提高(02)(就是多重背包)
【Done】洛谷P2254 [NOI2005]瑰丽华尔兹
【Todo】洛谷P2569 [SCOI2010]股票交易
【Todo】洛谷P3572 [POI2014]PTA-Little Bird
【Todo】洛谷P3594 [POI2015]WIL-Wilcze doły
决策单调性
一般分两类。无论是哪一类都需要细心发现决策之间的递变规律。
一种是用于优化形如\(f_{i}=\min/\max w_{i,j}\)且对于每一个\(i\)和它的最优决策点\(j\)都有单调性的方程。
这样的方程对题目的性质要求较高(因为\(j\)是独立的)。
只需要维护指针,按照单调性不断寻找最优答案即可。
update:上面提到的这一种好像不在狭义的决策单调性的定义内。。。应该可以叫双指针优化。
另一种是形如\(f_i=\min/\max_{j=1}^{i-1} g_j+w_{i,j}\),且记\(f_i\)的最优决策点为\(p_i\)(也就是\(f_i\)从\(g_{p_i}+w_{i,p_i}\)处转移最优)若满足\(p_i\le p_{i+1}\),则该方程满足决策单调性。
在诗人小G的题解中蒟蒻用数形结合的思想讨论了一种可能可以快速准确地判断一个转移方程是否满足决策单调性的方法。
因为\(j\)不独立了,所以我们只能把有用的决策先存起来。
策略1——二分栈
我们使用决策二分栈(一种单调栈)来维护所有有用的决策,其中栈顶是当前最优决策。
为什么叫二分栈呢?
我们可以把\(g_j+w_{i,j}\)视为关于\(j\)的函数。因为决策单调,所以对于栈中的任意相邻两个决策点,我们都可以通过二分找到一个临界值\(k\),使得序列中在\(k\)之前的时候,其中一个作为决策转移到\(f_k\)更优,而\(k\)以后另一个更优。可以借助函数图像来理解这个过程。
我们需要栈顶为当前的最优解。而如果栈中有不止一个元素,则可能存在一个\(i\),使得到\(i\)之后栈里面的决策比栈顶优了。这个时候,如何快速判断并弹掉栈顶呢?
上面提到的这个可二分的性质就派上用场了。对于当前的\(i\),如果当前栈顶下面与栈顶相邻的决策在\(i\)之前就比栈顶更优了,就要把栈顶弹掉。
这是决策单调性的基本思想,具体的题目实现起来也不一样。诸如有的题为了扩展功能,还需要把单调栈换成单调队列,等等。
策略2——分治
然而二分栈有一个局限性,那就是必须能快速计算\(w_{i,j}\)。如果不能\(O(1)\)算的话,在求临界值\(k\)的时候复杂度会严重退化。
既然转移过程是单调并且离线的,我们考虑分治。假设当前我们求解一段区间\(f_{l,r}\),而所有\(f_{l,r}\)的最优决策点在\([L,R]\)之间。对于\([l,r]\)的中点\(mid\),我们可以暴力扫一遍\(L-mid\),找到它的最优决策点\(k\)。因为决策单调,所以\(f_{l,mid-1}\)的决策落在\([L,k]\)上,而\(f_{mid+1,r}\)的决策落在\([k,R]\)上,变成了两个规模减半的小问题。
套用分治的复杂度分析,总的时间也是\(n\log n\)的。
两种策略的代码难度都不大呢~
废话,DP当然是重在思维啦!
题目
类型1
【Todo】洛谷P3724 [AH2017/HNOI2017]大佬
类型2
【Done】BZOJ4709 [Jsoi2011]柠檬
【Sol.】洛谷P3515 [POI2011]Lightning Conductor
【Sol.】CF868F Yet Another Minimization Problem(洛谷)(vjudge)
斜率优化
与决策单调性有着说不清的联系。
仍然是转移方程形如\(f_i=\min_{j=1}^{i-1}g_j+w_{i,j}\)(\(\max\)同理)
考虑两个决策\(j_1,j_2\),如果\(j_1\)比\(j_2\)优,那么\(g_{j_1}+w_{i,j_1}\le g_{j_2}+w_{i,j_2}\)。
这时候根据题目特点把\(w\)展开,如果式子能化成\(\frac{y_{j_1}-y_{j_2}}{x_{j_1}-x_{j_2}}\le k_i\)的形式,那么我们把每个决策看成点\((x_j,y_j)\)分布在坐标系上,而真正有用的决策点实际上形成了一个凸壳。(由类似线性规划的寻找最优解的过程可以发现)
上面这段不好理解?下面第一题的Sol对两种理解斜率优化的方法做了更详细的分析(最好看第二种,因为第一种有针对性,不通用)(有图片哟qwq)
于是我们用数据结构维护凸壳上的所有点,具体实现依题而定。
不管是什么题,加入决策点的时候要保证斜率递增/递减。
如果\(x\)单调,可以用单调栈维护凸壳,转移时使用当前直线的斜率(线性规划),在栈内二分最优解。
如果斜率\(k\)单调,那么用单调队列维护凸壳,队首为当前最优决策。转移之前如果队首不优就出队。
引用MashiroSky学长的更完整的套路总结(他的总结戳这里)
斜率单调暴力移指针
斜率不单调二分找答案
x坐标单调开单调队列
x坐标不单调开平衡树|cdq分治
题目
【Sol.】洛谷P2900 [USACO08MAR]土地征用Land Acquisition
【Todo】洛谷P3195 [HNOI2008]玩具装箱TOY
【Todo】洛谷P4360 [CEOI2004]锯木厂选址
【Todo】洛谷P2305 [NOI2014]购票
【Todo】洛谷P1721 [NOI2016]国王饮水记
DP凸优化/WQS二分/带权二分
这种算法用来解决一类问题——有\(n\)个物品,规定以若干方式选择物品有若干代价,需要在强制选出\(C\)个物品的前提下最大/最小化代价。
一般来说,适用此算法的题目还要有如下一些特点:(设关于\(x\)的函数\(g(x)\)为强制选\(x\)个物品的最值)
- 我们无法直接求出\(g(C)\)的值(废话,不然干嘛不直接求);
- 我们可以直接求出\(g\)的最值,以及使\(g(x)\)取到最值的\(x\);
- \(g\)是一个凸函数。
蒟蒻再解释这是个什么东东也比不上Creeper_LKF大佬的blog来的清楚明白了。
可是,有没有大佬和蒟蒻一样觉得用二分斜率切凸包的这种思路有点不好理解呢?
受超级大佬学哥的启发,蒟蒻想试着用原函数与导数的相互转化来理解我们寻找刚好选取\(C\)个物品时的最优解。
这是\(g(x)\)(上方蓝色曲线)和\(g'(x)\)(下方红色曲线)
设\(C=7\),现在我们的任务就是求出\(g(7)\)。
显然,因为\(g(x)\)是凸的,所以\(g'(x)\)是单调递减的。我们可以求出现在\(g(x)\)的最值,有什么特点呢?看看\(g'(x)\)与\(x\)轴相交的地方,不就是在这个点处\(g(x)\)取到最值么?
然而这个交点\(x=5\),不是我们想要的。如果我们能把函数膜改一下,使导函数的交点挪到\(x=7\),那该有多好!
设\(f(x)=g(x)+kx\),\(k\)的现实意义是,我们每多选一个物品,就要多付出\(k\)的代价。
那\(k\)的函数意义又是什么呢?我们显然可以发现\(f'(x)=g'(x)+k\),相当于导函数向上平移了\(k\)个单位!而导函数是递减的,如果我们把它向上平移,那它与\(x\)轴的交点就会向右移了。等于说\(k\)越大交点的\(x\)也越大。这个样子是可二分的。
于是我们对\(k\)进行二分,\(k\)的值域就是导函数的值域。我们做一遍DP,在原有的转移基础上,每多选一个物品还要额外加上\(k\)的代价。最后,我们可以求得\(f(x)\)的极值点,也就是\(f'(x)\)与\(x\)轴的交点。如果这个交点\(x<C\)说明我们仍需继续调大\(k\),否则就是调小咯。
现在我们试着模拟一下。一开始\(k\)等于\(0\)的时候交点\(x=5<C\),我们就把\(k\)调大一点点。
图中多了\(f(x)\)(上方绿色曲线)和\(f'(x)\)(下方橙色曲线)
现在的交点\(x=9\),又比\(7\)大了,我们调小\(k\)。
又经过若干调整,我们终于使得交点落在了\(C\)这个位置。
那么我们要求出\(g(C)\)了。我们现在求出的是\(f(C)\),只需要\(g(C)=f(C)-kC\)即可,等于说减掉函数图像中\(f(x)\)与\(g(x)\)在\(C\)处的高度差。
看上去需要小数二分?不是这样的。在实际的DP问题中\(x\)肯定都是整数点,那么\(g(x)\)肯定是一段一段的折线,\(g'(x)\)就是一段一段的水平线,等于说取遍\(g'(x)\)的整数点的值就能取遍\(g'(x)\)的整个值域了。于是在整数内二分即可。
注意上面的\(g(x)\)是上凸的,如果\(g(x)\)下凸那么\(g'(x)\)递增,二分的方向还要变一下。
题目
【Sol.】洛谷P2619 [国家集训队2]Tree I(不是DP,但有助于理解带权二分)
【Done】洛谷P4383 [八省联考2018]林克卡特树lct
【Todo】BZOJ5311贞鱼
【Todo】洛谷CF739E Gosha is hunting
DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)的更多相关文章
- 【BZOJ5311/CF321E】贞鱼/Ciel and Gondolas(动态规划,凸优化,决策单调性)
[BZOJ5311/CF321E]贞鱼/Ciel and Gondolas(动态规划,凸优化,决策单调性) 题面 BZOJ CF 洛谷 辣鸡BZOJ卡常数!!!!!! 辣鸡BZOJ卡常数!!!!!! ...
- 6.13校内互测 (DP 带权二分 斜率优化)
丘中有麻plant 改自这儿,by ZBQ. 还有隐藏的一页不放了.. 直接走下去的话,如果开始时间确定那么到每个点的时间确定,把time减去dis就可以去掉路程的影响了. 这样对于减去d后的t,如果 ...
- BZOJ_4609_[Wf2016]Branch Assignment_决策单调性+带权二分
BZOJ_4609_[Wf2016]Branch Assignment_决策单调性+带权二分 Description 要完成一个由s个子项目组成的项目,给b(b>=s)个部门分配,从而把b个部门 ...
- BZOJ_5311_贞鱼_决策单调性+带权二分
BZOJ_5311_贞鱼_决策单调性+带权二分 Description 众所周知,贞鱼是一种高智商水生动物.不过他们到了陆地上智商会减半. 这不?他们遇到了大麻烦! n只贞鱼到陆地上乘车,现在有k辆汽 ...
- 洛谷 4383 [八省联考2018]林克卡特树lct——树形DP+带权二分
题目:https://www.luogu.org/problemnew/show/P4383 关于带权二分:https://www.cnblogs.com/flashhu/p/9480669.html ...
- 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)
题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...
- Codeforces.739E.Gosha is hunting(DP 带权二分)
题目链接 \(Description\) 有\(n\)只精灵,两种精灵球(高级和低级),每种球能捕捉到第\(i\)只精灵的概率已知.求用\(A\)个低级球和\(B\)个高级球能捕捉到精灵数的最大期望. ...
- 洛谷P2900 [USACO08MAR]土地征用Land Acquisition(动态规划,斜率优化,决策单调性,线性规划,单调队列)
洛谷题目传送门 用两种不一样的思路立体地理解斜率优化,你值得拥有. 题意分析 既然所有的土地都要买,那么我们可以考虑到,如果一块土地的宽和高(其实是蒟蒻把长方形立在了平面上)都比另一块要小,那么肯定是 ...
- bzoj4518: [Sdoi2016]征途(DP+决策单调性分治优化)
题目要求... 化简得... 显然m和sum^2是已知的,那么只要让sigma(si^2)最小,那就变成了求最小平方和的最小值,经典的决策单调性,用分治优化即可. 斜率优化忘得差不多就不写了 #inc ...
随机推荐
- 如何学习 Webpack
webpack-howto Tip: 本文是 webpack-howto 的原文,我觉得这篇文章写得非常好,确实算是目前学习 webpack 入门的必读文章.直接收录之. 本教程的目标 这是一本教你如 ...
- linux shell的here document用法
转载自: http://my.oschina.net/u/1032146/blog/146941 什么是Here Document?Here Document 是在Linux Shell 中的一种特殊 ...
- kettle学习笔记——插件的安装与使用
一.概述 暂略 二.ODPS插件 https://yq.aliyun.com/articles/68911
- iisapp -a命令出现 :此脚本不能与WScript工作
今天一个同事向我反馈,使用iis的命令时出现了如标题的问题. 通过百度,找到如下信息: iisapp实际上是存放在C:\windows \system32目录下的一个VBS脚本,全名为iisapp.v ...
- 从0到1上线一个微信小程序
0.0 前期准备 微信小程序的出现极大地降低了个人开发者微创业的门槛,不需要后端技术,不需要服务器和域名这些乱七八糟的前置操作,只需要懂得前端技术,就能发布一款属于自己的轻量级应用,简直是前端开发者的 ...
- Jmeter(二十九)_dotnet搭建本地接口服务
这里使用的服务名为Bookshelf,在github上,自行下载.要运行此服务,需要.Net Core SDK 2.1或更高版本.如果尚未安装,从.Net Core官方网站下载并安装. 在本地克隆项目 ...
- Nginx反向代理的简单实现
1)nginx的反向代理:proxy_pass2)nginx的负载均衡:upstream 下面是nginx的反向代理和负载均衡的实例: 负载机:A机器:103.110.186.8/192.168.1. ...
- LVM常规操作记录梳理(扩容/缩容/快照等)
基本介绍Linux用户安装Linux 操作系统时遇到的一个最常见的难以决定的问题就是如何正确地给评估各分区大小,以分配合适的硬盘空间.随着 Linux的逻辑盘卷管理功能的出现,这些问题都迎刃而解, l ...
- 最好使用%f输出浮点数据,acm
今天做题的时候发现使用%lf输出的时候总是wrong,而一旦改成%f就ac了,询问学长后知道,不要用%lf输出,浮点都用%f 然而我还是有疑惑,如果%f容不下输出的数据怎么办呢? 于是我就去百度 原来 ...
- 《Linux内核分析》实践2
<Linux及安全>实践2 一.Linux基本内核模块 1.1什么是内核模块 linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一 ...