斜率优化
斜率优化,一种优化 1D/1D 转移 dp 的方式,即将转移方程化为一次函数 $y=kx+b$ 的形式,再利用建模转化,将转移变成在某些数据结构上,比如单调队列、单调栈、李超树的操作,以此来优化转移时间复杂度。
一般来说(我感觉)斜率优化的转移方程里常常见到 $s_is_j$ 的形式。
例子:AT_dp_z Frog 3
容易写出 dp 方程
化简得到
发现 $s_i$ 单调递增,即作为斜率的 $2s_i$ 单调递增,利用单调队列维护凸包可以做到 $O(n)$。
例子:P2365&P5785 任务安排两件套
P2365 可以用暴力过去。
首先考虑到时间花费中的 $s$ 依赖于前面的决策段数,这不利于进行转移(暴力就无所谓了 XD),因此考虑把划分的时间额外开销进行贡献转化。考虑如果在这里划分,后面的所有部分都会有贡献,其贡献是 $s\cdot\sum\limits_{j=i}^nf_j$。
然后可以写出转移方程了。这里 $t_i>0$,因此前缀和是单增的,因此可以使用单调队列 $O(n)$。
然而在 P5785 中,$|t_i|\le2^8$,这表明 $t_i$ 不保证是正的(唐氏吗完成任务还倒贴时间了是吧),此时斜率不保证单增(但能得 60 分),因此拿二分队列做就可以了,时间复杂度 $O(n\log n)$。
更加劲爆的例子:P1721 国王饮水记
更详细的介绍可见这个课件。
Lemma 1 你发现如果一个水位 $h_i<h_1$,那么这个水位一定不会造成任何贡献。直接删掉!
Lemma 2 每个水缸最多会和 $1$ 连接一次。因为连接一次后他俩就一样高了,不会再造成贡献了。
Lemma 3 每次联通的时候都会有 $1$。可以证明 Lemma 2 与 Lemma 3 是等价的。
Lemma 4 当 $k\rightarrow\infty$ 时最优操作为将 $h_i$ 从小到大排序后依次向上一个一个取平均。
你发现一次操作可以被拆成若干次 $1$ 节点与单个节点的平衡,而有式子
此处 $h_1<h_2<h_3$。
于是对于任意两个节点,一定是水量小的与 $1$ 先连接,再让水量大的连接。
非常自然地想到要对 $h$ 排序并去掉比 $h_1$ 小的元素。
有了这些性质可以敲出一个 $O(k3^n)$ 的状压 dp 来。
同时根据 Lemma 2,4 可以知道有效操作数量不会超过 $O(n)$,直接取 $\min$ 是对的。
写一个取最大 $K$ 个的贪心。等等,为什么我的得分比 $45$ 高这么多?——《NOI2016 国王饮水记 讲课ppt》
然后又有 $3$ 个重要的定理:
Lemma 5 每次操作选择的城市的最小水量一定大于上一操作的最大水量。否则你交换两个逆序的城市按照 Lemma 4 会变得更优。
Lemma 6 每次操作选择的一定是个区间。可以找规律对吧如果不是区间,那么把选择的最小水量城市换成任意一个断点都会变优。
Lemma 7 每次操作选择的区间连续。否则把左边区间向右移一定更优。
到这里转移变成区间了!
设 $dp_{i,j}$ 表示考虑到第 $i$ 个城市并且进行了 $j$ 次操作的最大水位,则有转移方程
其中 $s_i$ 表示水量前缀和。
直接转移时间复杂度是 $O(n^2kp)$ 的。
你重新审视一下这个方程,设最优决策点为 $k$,给他变形得到
虽然这不是斜率优化常见的式子形式 $y=kx+b$,但是这个却是斜率的表达式
因此也可以斜率优化,其中凸包上的点为 $(k-1,s_k-dp_{k,j-1})$。
当前转移点就是过点 $(i,s_i)$ 的凸包上点的斜率最小值,可以用三分来求出,时间复杂度被优化到 $O(nkp\log n)$。
但是这样只能过 $70$ 分,考虑继续优化。
Lemma 8 决策点有单调性。
假设两个决策点为 $k>l$ 且 $k$ 比 $l$ 优,按照定义有 $dp_{k,j-1}\ge dp_{l,j-1}$。然后你对不等式做一个变形
得证。
得到决策单调性之后利用单调队列可以少一个 $\log$。
还可以优化?
注意到水量高度互不相同,可以知道每一次操作的区间长度不会大于上一次的区间长度。感性的想就是越往后走高度越大,显然拿更少的位置来平分会更优。另一个奇妙的性质是:长度大于 $1$ 的决策区间很少,只有 $O(\log\frac{nk}{\Delta})$,其中 $\Delta=\min\{h_i-h_{i-1}\}$。
为什么我也不会了。
这样子就不用 dp $k$ 层了,只需要 dp 这么多层就可以了。
时间复杂度是 $O(np\log nh)$。
但是居然还有 $O(n(\log^3nh+p))$ 的做法在 ppt 里?太奆了不会。
给个高精小数 Decimal 类还是很善良的!
一些很蠢的事情
警钟爆破队长
求斜率的常见计算方式是
但是这样是要用实数的,爆精度就似了。考虑移项之后用乘法保住精度。
但是很重要的一个细节是 $x(i)-x(j)$ 不要写反,一定是大减小,不然移项的时候会导致不等式方向变化就似了。
警钟爆破队员 1 号
@P2120。
你发现这个题很简单对吧!
考虑设 $dp_i$ 表示在第 $i$ 个工厂上建造仓库的最小开支。
但是你发现转移的时候 $val(l,r)$ 不易计算,需要展开一下。
具体的:
我们记 $s1_i=\sum\limits_{j=1}^ip_j$,$s2_i=\sum\limits_{j=1}^ip_jx_j$,那么上式化简为
你写出 dp 方程:
设 $j$ 是转移最优决策点则有
化简得
这就是斜率优化的板子了,注意到 $x_i$ 单调递增于是直接 $O(n)$。
于是你迅速地敲完了这个题,测试样例,通过了!
然后你提交,诶,怎么 Unaccepted 100分啊?你很生气。
你百思不得其解,打开讨论区,全是诸如被hack力,求调(悲此类的东西。你随便打开了一个,看到这样一句话:
最后可能会有一长条 $p_i=0$ 的可(毒)爱(瘤)工厂,最后答案是尾巴上所有 $p_i=0$ 的工厂的 dp 值取 $\min$。
你怀着愤恨的心情去骂 ZJOI2007 的出题人没有良心。