DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)

前缀和优化

当DP过程中需要反复从一个求和式转移的话,可以先把它预处理一下。运算一般都要满足可减性。

比较naive就不展开了。

题目

【Todo】洛谷P2513 [HAOI2009]逆序对数列

【Done】洛谷P2511 [HAOI2008]木棍分割

【Done】洛谷P4099 [HEOI2013]SAO

【Done】NOIAC37 染色

单调队列优化

前置技能:单调队列(经典的问题模型:洛谷P1886 滑动窗口

用于优化形如fi=min/maxj=lii1{gj}+wi,且满足lili+1的转移。

人话:对于序列中的每个点,从其左侧一段决策区间内的最值进行转移,且决策区间随着序列下标的增大也不断右移(就像窗口向右滑动)。

j<k,容易发现如果gj劣于gk的话,那么当决策区间移动到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

决策单调性

一般分两类。无论是哪一类都需要细心发现决策之间的递变规律。

一种是用于优化形如fi=min/maxwi,j且对于每一个i和它的最优决策点j都有单调性的方程。

这样的方程对题目的性质要求较高(因为j是独立的)。

只需要维护指针,按照单调性不断寻找最优答案即可。

update:上面提到的这一种好像不在狭义的决策单调性的定义内。。。应该可以叫双指针优化。

另一种是形如fi=min/maxj=1i1gj+wi,j,且记fi的最优决策点为pi(也就是figpi+wi,pi处转移最优)若满足pipi+1,则该方程满足决策单调性。

在诗人小G的题解中蒟蒻用数形结合的思想讨论了一种可能可以快速准确地判断一个转移方程是否满足决策单调性的方法。

因为j不独立了,所以我们只能把有用的决策先存起来。

策略1——二分栈

我们使用决策二分栈(一种单调栈)来维护所有有用的决策,其中栈顶是当前最优决策。

为什么叫二分栈呢?

我们可以把gj+wi,j视为关于j的函数。因为决策单调,所以对于栈中的任意相邻两个决策点,我们都可以通过二分找到一个临界值k,使得序列中在k之前的时候,其中一个作为决策转移到fk更优,而k以后另一个更优。可以借助函数图像来理解这个过程。

我们需要栈顶为当前的最优解。而如果栈中有不止一个元素,则可能存在一个i,使得到i之后栈里面的决策比栈顶优了。这个时候,如何快速判断并弹掉栈顶呢?

上面提到的这个可二分的性质就派上用场了。对于当前的i,如果当前栈顶下面与栈顶相邻的决策在i之前就比栈顶更优了,就要把栈顶弹掉。

这是决策单调性的基本思想,具体的题目实现起来也不一样。诸如有的题为了扩展功能,还需要把单调栈换成单调队列,等等。

策略2——分治

然而二分栈有一个局限性,那就是必须能快速计算wi,j。如果不能O(1)算的话,在求临界值k的时候复杂度会严重退化。

既然转移过程是单调并且离线的,我们考虑分治。假设当前我们求解一段区间fl,r,而所有fl,r的最优决策点在[L,R]之间。对于[l,r]的中点mid,我们可以暴力扫一遍Lmid,找到它的最优决策点k。因为决策单调,所以fl,mid1的决策落在[L,k]上,而fmid+1,r的决策落在[k,R]上,变成了两个规模减半的小问题。

套用分治的复杂度分析,总的时间也是nlogn的。


两种策略的代码难度都不大呢~

废话,DP当然是重在思维啦!

题目

类型1

Sol.洛谷P1973 [NOI2011]Noi嘉年华

【Todo】洛谷P3724 [AH2017/HNOI2017]大佬

类型2

【Done】BZOJ4709 [Jsoi2011]柠檬

Sol.洛谷P3515 [POI2011]Lightning Conductor

Sol.洛谷P1912 [NOI2009]诗人小G

Sol.CF868F Yet Another Minimization Problem洛谷)(vjudge

斜率优化

与决策单调性有着说不清的联系。

仍然是转移方程形如fi=minj=1i1gj+wi,jmax同理)

考虑两个决策j1,j2,如果j1j2优,那么gj1+wi,j1gj2+wi,j2

这时候根据题目特点把w展开,如果式子能化成yj1yj2xj1xj2ki的形式,那么我们把每个决策看成点(xj,yj)分布在坐标系上,而真正有用的决策点实际上形成了一个凸壳。(由类似线性规划的寻找最优解的过程可以发现)

上面这段不好理解?下面第一题的Sol对两种理解斜率优化的方法做了更详细的分析(最好看第二种,因为第一种有针对性,不通用)(有图片哟qwq)

于是我们用数据结构维护凸壳上的所有点,具体实现依题而定。

不管是什么题,加入决策点的时候要保证斜率递增/递减。

如果x单调,可以用单调栈维护凸壳,转移时使用当前直线的斜率(线性规划),在栈内二分最优解。

如果斜率k单调,那么用单调队列维护凸壳,队首为当前最优决策。转移之前如果队首不优就出队。

引用MashiroSky学长的更完整的套路总结(他的总结戳这里

  斜率单调暴力移指针
  斜率不单调二分找答案
  x坐标单调开单调队列
  x坐标不单调开平衡树|cdq分治

题目

Sol.洛谷P2900 [USACO08MAR]土地征用Land Acquisition

【Todo】洛谷P3195 [HNOI2008]玩具装箱TOY

Sol.洛谷P3628 [APIO2010]特别行动队

【Todo】洛谷P4360 [CEOI2004]锯木厂选址

【Todo】洛谷P2305 [NOI2014]购票

【Todo】洛谷P1721 [NOI2016]国王饮水记

DP凸优化/WQS二分/带权二分

WQS的论文(在线)(下载

这种算法用来解决一类问题——有n个物品,规定以若干方式选择物品有若干代价,需要在强制选出C个物品的前提下最大/最小化代价。

一般来说,适用此算法的题目还要有如下一些特点:(设关于x的函数g(x)为强制选x个物品的最值)

  1. 我们无法直接求出g(C)的值(废话,不然干嘛不直接求);
  2. 我们可以直接求出g的最值,以及使g(x)取到最值的x
  3. 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)+kxk的现实意义是,我们每多选一个物品,就要多付出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,但有助于理解带权二分)

Sol.洛谷P4072 [SDOI2016]征途

【Done】洛谷P4383 [八省联考2018]林克卡特树lct

【Todo】BZOJ5311贞鱼

【Todo】洛谷CF739E Gosha is hunting

posted @   Flash_Hu  阅读(22506)  评论(44编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示
哥伦布
-1°
10:09发布
哥伦布
10:09发布
-1°
西南风
2级
空气质量
相对湿度
87%
今天
小雨
-1°/13°
周六
多云
-3°/10°
周日
-4°/2°