基于单调性的 DP 优化
决策单调性
决策单调性一般用于最优性问题当中,即一个状态只能从一个最优的状态转移,该最优状态称之为最优点。决策单调性就是指最优点随 dp 转移单调移动。
一般如果能够将 dp 转移方程写成如下形式:
且函数 \(w(j, i)\) 满足一些特殊的性质时,我们可以利用决策的单调性进行优化。
四边形不等式
下文讨论均以求最小值为例,若求最大值需要将不等式取反。
- 区间包含单调性: 如果 \(\forall l_1 \leq l_2 \leq r_2 \leq r_1, w(l_2, r_2) \leq w(l_1, r_1)\),则称 \(w(l, r)\) 满足区间包含单调性。
- 四边形不等式: 如果 \(\forall l_1 \leq l_2 \leq r_2 \leq r_1, w(l_1, r_1) + w(l_2, r_2) \leq w(l_1, r_2) + w(l_2, r_1)\),即 交叉优于包含,我们称 \(w(l, r)\) 满足四边形不等式。
若等号恒成立,则称其满足 四边形恒等式。
证明四边形不等式的基本方法
推论: 若函数 \(w(l, r)\) 满足 \(\forall l < r, w(l, r) + w(l + 1, r + 1) \leq w(l, r + 1) + w(l + 1, r)\),则函数 \(w(l, r)\) 满足四边形不等式。
证明:
考虑归纳法证明。
首先,对于 \(l_1 = l_2\) 或 \(r_1 = r_2\),显然恒相等。
对于 \(l < r\),有 \(w(l, r) + w(l + 1, r + 1) \leq w(l, r + 1) + w(l + 1, r)\)。
对于 \(l + 1 < r\),有 \(w(l + 1, r) + w(l + 2, r + 1) \leq w(l + 1, r + 1) + w(l + 2, r)\)
两式合并得到,\(w(l, r) + w(l + 2, r + 1) \leq w(l, r + 1) + w(l + 2, r)\)。
以此类推得到,\(\forall l \leq l' \leq r, w(l, r) + w(l', r + 1) \leq w(l, r + 1) + w(l', r)\)。
对 \(r\) 进行类似的操作可以得到,\(\forall l \leq l' \leq r \leq r', w(l, r) + w(l', r') \leq w(l, r') + w(l', r)\)。
一般情况可以用一种方式感性判断函数 \(w(l, r)\) 是否具有四边形不等式:考虑对于区间 \([l_2, r_1]\) 的代价,区间 \([l_1, l_2)\) 和区间 \((r_1, r_2]\) 对区间 \([l_2, r_1]\) 产生的代价,和区间 \([l_1, l_2)\) 与区间 \((r_1, r_2]\) 相互之间的产生的代价分别讨论。
考场上还可以通过打表找规律的方式来解决。
满足四边形不等式的函数类
性质1: 若函数 \(w_1(l, r), w_2(l, r)\) 均满足四边形不等式(或区间包含单调性),则对于任意 \(c_1, c_2 \geq 0\),满足 \(c_1 w_1 + c_2 w_2\) 满足四边形不等式(或区间包含单调性)。
性质2: 若存在函数 \(f(x), g(x)\) 使得函数 \(w(l, r) = f(r) - g(l)\),则函数 \(w\) 满足四边形 恒等式。当函数 \(f, g\) 单调递增(取 \(\max\) 的时候递减)时,函数 \(w\) 满足区间包含单调性。
性质3: 若函数 \(h(x)\) 是一个单调递增(取 \(\max\) 的时候递减)的凸函数,且函数 \(w(l, r)\) 满足四边形不等式和区间包含单调性,则复合函数 \(h(w(l, r))\) 满足四边形不等式和区间包含单调性。
性质3: 若函数 \(h(x)\) 是一个凸函数,且函数 \(w(l, r)\) 满足四边形恒等式和区间包含单调性,则复合函数 \(h(w(l, r))\) 满足四边形不等式。
决策单调性在 1D 转移中的应用
定义: 对于形如 \(f_i = \min_{0 \leq j < i}(f_j + w(j, i))\) 的状态转移方程,记 \(p_i\) 为 \(f_i\) 的最优决策点,若满足 \(p_i\) 随 \(i\) 单调递增,则称 \(f\) 具有决策单调性。
定理: 对于形如 \(f_i = \min_{0 \leq j < i}(f_j + w(j, i))\) 的状态转移方程,若 \(w\) 满足四边形不等式,则 \(f\) 具有决策单调性。
证明:
由最优点定义可得:\(f(p_i) + w(p_i, i) \leq f(q) + w(q, i) \quad (q < p_i)\)
由 \(w\) 满足四边形不等式可得:\(w(p_i, i') - w(p_i, i) \leq w(q, i') - w(q, i) \quad (i < i')\)
两式相加可得:\(f(p_i) + w(p_i, i') \leq f(q) + w(q, i')\)。
由此可得,在 \(p_i\) 之前的所有转移状态均不可能比 \(p_i\) 优秀,所以 \(p_i \leq p_{i'}\),所以 \(f\) 具有四边形不等式。
分治
若状态转移分为多层,且每一层皆只从上一层转移过来,则可以使用分治法做到 \(O(kn \log n)\) 的复杂度,其中 \(k\) 是状态层数。
比如以下两个状态转移方程就可以使用分治法求解:
其中 \(a\) 是初始给定的值。
算法简介
考虑每次取区间中点 \(mid\) 并暴力求出 \(mid\) 的最优决策点 \(p_m\),然后递归处理区间 \([l, mid), (mid, r]\),和决策范围 \([p_l, p_m], [p_m, p_r]\)。
对于分治的每一次暴力枚举决策点时间复杂度 \(O(n)\),分治树高 \(O(\log n)\),单层时间复杂度 \(O(n \log n)\)。
Trick
技巧1: 若题目限制选取物品个数 \(k\),可以考虑每次只选一个物品进行扩展,复杂度 \(O(kn log n)\)。如果满足凸性当然也可以使用更优秀的 wqs 二分。
技巧2: 若我们无法直接得到两个位置之间的答案,可以类比莫队,移动决策点指针来计算代价。时间复杂度为 \(O(nv \log n)\)。其中 \(O(v)\) 是单次移动指针的复杂度。
例题
CF833B
P5574 [CmdOI2019]任务分配问题
CF1603D
[雅礼集训 2017 Day5]珠宝
二分队列
对于形如 \(f_i = \min_{j < i} \{ f_i + w(i, j)\}\),若满足对于 \(i < j\) 则一定满足 \(p_i \leq p_j\),则可以用二分队列进行优化。
一般情况下:贡献函数满足四边形不等式即可(上文以证)。
算法简介
建立一个三元组队列 \((p, l, r)\),表示区间 \([l, r]\) 的最优决策点是 \(p\)。初始队列放入 \((0, 1, n)\),队首出队条件为 \(r < i\),队尾出队条件为 \(i\) 比队尾 \(p\) 转移到 \(l\) 更优秀。
然后取出队尾三元组 \((p, l, r)\),二分出一个 \(mid\) 表示 \(mid\) 之后的位置从 \(i\) 转移更优。如果满足有一段区间当前从 \(i\) 转移更优,就将 \(i\) 入队,并将队尾的 \(r\) 改为 \(mid - 1\)。
一些实现上的技巧:队列不用真正的去使用三元组维护,实际上知道了下一个元素的 \(l'\),当前元素的 \(r = l' - 1\)。最后一个元素的 \(r = n\)。所以只需要记录每个位置的最优点,以及队列中每个元素对应的左边界即可。
例题
P1912 [NOI2009] 诗人小G
P3515 [POI2011]Lightning Conductor
二分栈
注意此算法并不属于决策单调性。
对于形如 \(f_i = \min_{j < i} \{ f_i + w(i, j)\}\),若满足对于每种决策只会被它前面的决策超越,而一旦被超越后就永无翻身之日,则可以用二分栈进行优化。
与二分队列进行比较:
二分队列能够处理贡献函数二阶导非负求最小值,二阶导非正求最大值。
二分栈能够处理贡献函数二阶导非负求最大值,二阶导非正求最小值。
算法简介
用栈维护所有可能的决策点,栈顶为当前的最优决策点。
考虑如何更新决策点集合。有一个常有的错误思路: 如果栈顶劣于次栈顶弹出。错误在于如果存在 \(i < j < k\),使得 \(i\) 优于 \(k\) 但 \(k\) 优于 \(j\),就会得到错误的转移。
出现这种情况的那么一定满足在上一次转移中 \(j\) 优于 \(i\),但此时 \(i\) 能够反超 \(j\)。那么我们可以二分出一个决策反超另一决策的时间,如果满足 \(i\) 反超 \(j\) 在 \(j\) 反超 \(k\) 的时间之前,那么 \(j\) 就永远不会反超 \(k\) 成为最优点。
因此,可以在加入当前决策前,二分出次栈顶超过栈顶的时间 \(t_1\),栈顶超过当前决策点的时间 \(t_2\),一直弹栈直到 \(t_1 > t_2\) 或者栈中只剩一个元素。
在加入当前决策后,二分出当前次栈顶超过栈顶的时间 \(t\),一直弹栈直到 \(t\) 在当前需要转移的状态的时间之后。现在栈顶决策即为当前状态的最优点。
例题
P5504 [JSOI2011] 柠檬
斜率优化
咕咕咕
凸优化(wqs 二分)
wqs 二分常见于限制选取物品个数的最优性 dp。
算法简介
设 \(f(i)\) 表示选取最多,至少或恰好 \(i\) 个物品时的最优解,若 \(f\) 为凸函数则可以使用 wqs 二分进行优化。
考虑用一条斜率为 \(k\) 的直线去且点集 \((i, f_i)\) 构成的凸包,设切点为 \((p, f_p)\),那么截距 \(b = f_p - kp\)。我们能够通过二分调整选取的斜率来令切点的横坐标左右移动,从而使得我们要求的 \((i, f_i)\) 在这条切线上。此时答案为 \(b + ki\)。
那么通俗的来讲,我们可以把当前每个物品的权值看作它本身的权值减去 \(k\),此时我们求出现在不限制选取个数的答案和当前最优答案下选取了多少个物品,其分别对应这现在的截距 \(b\) 和切点的横坐标。
由此可见,此类问题需要满足在不限制物品的条件下能够方便地求出答案。
细节
三点共线
首先我们钦定,若当前状态能从多个状态得到最优答案,那么我们选取需要选取物品个数最少的转移方式。
若现在二分的斜率 \(k\) 的切点横坐标为 \(i\),斜率 \(k + dk\) 的切点横坐标为 \(j\),满足 \(i < x < j\),那么我们永远不可能切到我们想要的 \(x\)。可是容易发现,需求的 \(x\) 对应的斜率与截距都和 \(i\) 一致。所以我们可以得到,\(f_x = b + kx\)。
注意: \(f_x\) 增加的是 \(kx\) 而非 \(ki\),这是一个常见的错误。
对于一些题目需要判定有无解,如 P2619 [国家集训队] Tree I。我们可以转为判定斜率为 \(k\) 和 \(k + dk\) 的切点所对应的区间 \([l, r)\) 是否包含 \(x\)。
数据类型
对于 \(f\) 都为整数的题目,我们并只需要二分整数,这样既可以保证精度,又可以减小常数。
这么做的正确性在于对于相邻两点的斜率为 \(\frac{f_{i + 1} - f_i}{(i + 1) - i} = f_{i + 1} - f_i\),仍然为一个整数。
如果当前的切点横坐标恰好等于 \(x\),那么可以直接退出。
二分边界
二分边界一般为第一个点与第二个点之间的斜率 和 倒数第二个点和倒数第一个点之间的斜率。
例题
P2619 [国家集训队] Tree I
CF739E
注意此题讨论区中提到的 wqs 套 wqs 正确性并不对的问题。