2023.8.14 决策单调性优化DP + 斜率优化DP + wqs二分
决策单调性优化DP
假设我们有这样一个转移式:
\(f_i = \max\limits_{1 \le j < i} (g_j + w_{i, j})\)
我们发现 \(f_i\) 肯定是由前面的一个点转移过来
这里给出结论:若 \(w_{i, j}\) 满足四边形不等式 即 \(w_{i, j} + w_{i + 1, j + 1 } \le w_{i + 1, j} + w_{i, j + 1}\)
用通俗的话来讲 就是相交比包含更优
那么当 \(i\) 右移的时候 \(f_i\) 的决策点的位置单调不降
这里给出我自己的证明(不一定对):
考虑将上述四边形不等式移项 得 \(w_{i + 1, j + 1} - w_{i + 1, j} \le w_{i, j + 1} - w_{i, j}\)
我们考虑每次将决策点右移 比如说将决策点从 \(j\) 移到 \(j + 1\) 那么变化量为 \(g_{j + 1} - g_j + w_{i, j + 1} - w_{i, j}\)
显然上式只有 \(\le 0\) 时我们才会右移决策点 所以如果我们设 \(j\) 为 \(f_i\) 的决策点 那么显然有 \(g_{j + 1} - g_j + w_{i, j + 1} - w_{i, j} > 0\)
此时我们考虑把 \(i\) 移动到 \(i + 1\) 那么此时右移决策点的变化量就是 \(g_{j + 1} - g_j + w_{i + 1, j + 1} - w_{i + 1, j}\)
由于满足四边形不等式 所以下面那个式子一定小于等于上面的式子 即它更有可能右移
同理我们可以证明当 \(i\) 移动到 \(i + 1\) 时 左移决策点一定会比原来更不优
说句闲话 其实使用决策单调性是需要证明价值函数满足四边形不等式的 但是我更推荐你猜它是决策单调的然后用暴力 \(DP\) 记录决策点 然后多跑几组数据看就行 而且正解写出来之后直接就能上拍子 血赚(
针对决策单调性 我们就可以进行优化:
单调栈二分
首先对于每个位置的决策点 这玩意长得就很像个单调栈 所以我们直接用单调栈维护即可
我们每次要新往栈里面丢点的时候 分三种情况讨论:
-
它比栈顶元素管辖的整个区间都优 那么把栈顶弹出
-
它比栈顶元素管辖的整个区间都不优 那就直接把它丢掉
-
否则 我们就要二分这个区间内分割“栈顶元素更优”和“它更优”的那个断点
进而我们就可以实现 \(O(nlogn)\) 的转移
分治
观察决策点序列 还像什么 像整体二分
我们对于一个区间 \(\left[l, r\right]\) 暴力求出 \(mid\) 位置的决策点
那么对于 \(\left[l, mid\right]\) 这段区间的决策点显然就 \(\le mid\)
\(\left[mid + 1, r\right]\) 的决策点就 \(\ge mid\)
然后递归下去即可
因为对于每一层 求 \(mid\) 的决策点显然是 \(O(区间长度)\) 即 \(O(n)\) 的
又因为我们最多递归 \(logn\) 层 所以总复杂度就是 \(O(nlogn)\)
这个做法强大在哪里呢?有的时候价值函数 \(w_{i, j}\) 是不太好 \(O(1)\) 求出来的 但是移动 \(i\) \(j\) 时的转移是 \(O(1)\) 的 我们就可以用类似莫队的东西来求价值函数
以此题为例:CF868F Yet Another Minimization Problem
首先我们用 \(f_{i, j}\) 表示前 \(i\) 个数分成 \(j\) 份的最小代价
显然有 \(f_{i, j} = \min\limits_{1 \le k < i} (f_{k, j - 1} + calc(k, i))\)
然后通过各种手段猜出来这玩意满足决策单调性
我们发现 这个 \(calc\) 正好满足上面所说“端点移动 \(O(1)\)” 的性质
所以我们记录上次区间的左右端点 桶 和代价
看似这个复杂度会假 但是我们考虑每一层之间 \(l\) 和 \(r\) 都是不断右移的
总共有 \(logn\) 层 所以总共也只会移动 \(O(nlogn)\) 次
然后做 \(k\) 次就可以求得答案
斜率优化DP
首先还是需要满足决策单调性(头疼
考虑形如这样的 \(DP\) 式:
\(f_i = \min\limits_{1 \le j < i} {A_j + B_j * C_i}\)
我们考虑 当这个决策点可以右移的时候 一定满足 \(A_j + B_j * C_i \ge A_{j + 1} + B_{j + 1} * C_i\)
移项可得 \(C_i \ge \frac{A_{j + 1} - A_j}{B_{j + 1} - B_j}\)
我们就把这个东西转化成了类似于斜率的形式
我们考虑维护一个凸包 那么斜率是逐渐减小的 进而我们就可以二分求得 \(i\) 对应决策点的位置
关于凸包的维护:如果我们是按 \(B\) 从小到大插入 那么我们每次插入只需要判断它和凸包上前一个点的斜率与凸包上前一个点和凸包上前一个点的前一个点的斜率 如果是凹形 就把前一个点删掉 否则直接把当前点加入
注意到 当这几个量都具有单调性 实际我们可以直接用双指针来维护决策点的位置
具体地 我们每次插入一个点 就把它对应的 \((A_j, B_j)\) 插入凸包 然后考虑指针能否右移 进而求出当前点的答案
复杂度就变成了线性
很经典的斜率优化 首先我们发现方差一顿拆只需要维护平方和的最小值
然后我们考虑 \(f_{i, j}\) 表示前 \(i\) 个数分 \(j\) 段的最小平方和
那我们就有 \(f_{i, j} = \min\limits_{1 \le k < i} (f_{k, j - 1} + sum_{k + 1, i}) ^ 2\)

浙公网安备 33010602011771号