【学习笔记】DP 优化 5:wqs 二分优化 DP
概述
wqs 二分是一种优化带有数量限制的最优化问题的方式(即题目限制最多/最少/恰好选择 \(m\) 个物品时的最大/小值),要求关于数量的函数具有凸性。以最小值为例,要求函数是下凸的。
算法思想
由于状态数至少 \(O(nm)\),在朴素 DP 的基础上进行优化,时间复杂度也不会低于 \(O(nm)\),因此要想办法解除 \(m\) 的限制。
设函数 \(F_i\) 表示选择 \(i\) 个物品的最小值,考虑增加一个附加权值 \(k\),每选择一个物品需要增加 \(k\) 的代价,令 \(G_i=F_i+ki\),那么 \(G_i\) 也是下凸的,求出此时 \(G_i\) 的最小值对应位置 \((p,G_p)\),这实际上等价于用斜率为 \(-k\) 的直线去切 \(F_i\) 构成的凸包,对应的截距就是 \(G_p\)。
不难发现,由于凸函数的斜率具有单调性,可以二分 \(k\) 来找到使 \((m,G_m)\) 恰好为最小值的情况,这样就能将数量放入转移方程中,从而忽略严格的数量限制。
实现细节
存在一个可能的问题:\(F_i\) 可能出现多点共线的情况,即 \((m,F_m)\) 可能永远无法被切到。
若 \((m,F_m)\) 左右的斜率都为 \(K\),那么二分过程中,一定存在斜率为 \(K\) 的时刻,此时整个线段的截距都相等,自然可以计算。
同时在二分过程中,如果当前的 \(k\) 满足条件,那么直接更新答案为 \(G_p-km\),注意不是 \(G_p-kp\),也不是取 \(\min/\max\)。
二分之后,内层的处理一般是使用较为朴素的 DP 优化手段,例如斜率优化、决策单调性分治以及二分队列。
内层处理的 DP 可能存在值相同的情况,此时可以选择数量尽量多的方案,这样如果此时的 \(p\ge m\),则可能是合法答案,可以更新,否则不是。
函数凸性的证明
在大多数题目中,\(F_i\) 的凸性都是通过感性理解和打表来验证的,但也存在一部分题目具有良好的性质。
对于将 \([1,n]\) 划分为有数量限制的若干段求最值的区间划分问题,转移方程形如:
若 \(w(j,i)\) 满足四边形不等式,则 \(F_i=f_{i,n}\) 是凸函数。
证明从凸函数差分数组单调性入手,即证明 \(F_i-F_{i-1}\le F_{i+1}-F_i\Leftrightarrow 2F_i\le F_{i-1}+F_{i+1}\)。
考虑 \(F_{i-1}\) 对应的区间划分 \([a_1,d_1],[a_2,d_2]\cdots [a_{i-1},d_{i-1}]\) 以及 \(F_{i+1}\) 对应的区间划分 \([b_1,c_1],[b_2,c_2]\cdots [b_{i+1},c_{i+1}]\),找到最小的 \(j\) 使得 \(c_{j+1}\le d_j\),同时满足 \(b_{j+1}>a_j\),即 \(a_j<b_{j+1}\le c_{j+1}\le d_j\),此时将 \([a_j,d_j],[b_{j+1},c_{j+1}]\) 之后的区间交换,这两个区间交换右端点,即 \([a_1,d_1],[a_2,d_2]\cdots [a_j,c_{j+1}],[b_{j+2},c_{j+2}]\cdots [b_{i+1},c_{i+1}]\) 以及 \([b_1,c_1],[b_2,c_2]\cdots [b_{j+1},d_j],[a_{j+1},d_{j+1}]\cdots [a_{i-1},d_{i-1}]\)。
这样两个划分大小都是 \(i\)。设交换后两个方案的权值和 \(S\),由于 \(F_i\) 是最优方案,有 \(2F_i\le S\),同时根据四边形不等式,交换后的 \(w(a_j,c_{j+1})+w(b_{j+1},d_j)\le w(a_j,d_j)+w(b_{j+1},c_{j+1})\),那么 \(2F_i\le S\le F_{i-1}+F_{i+1}\),凸性得证。
满足四边形不等式的基础上,还可以使用二分队列来优化,一举两得。
例题
Luogu-P2619 国家集训队 Tree I
不是 DP 题目,但是是比较经典的 wqs 二分。
记 \(F_i\) 为选择 \(i\) 条白色边的最小生成树,数量尽量多对应排序时白边优先。
Luogu-P4983 忘情
整理一下发现就是 \((\sum x_i +1)^2\),满足四边形不等式所以是凸的,可以 wqs 二分。
内层用斜率优化或者二分队列均可。
AtCoder-JOISP2023_G ビーバーの合唱
首先通过调整,使得第 \(i\) 个 \(\texttt{A}\) 在第 \(i\) 个 \(\texttt{B}\) 之前,容易发现对于所有方案,这样的调整都是要进行的。
之后大致考虑一个 DP,\(f_{k,i}\) 表示当前把前 \(i\) 个 \(\texttt{A}\) 和 \(\texttt{B}\) 划分成 \(k\) 段的最小操作次数。
转移需要考虑贡献函数 \(w(j,i)\) 表示将第 \([j+1,i]\) 的 \(\texttt{A}\) 和 \(\texttt{B}\) 调整成所有 \(\texttt{A}\) 都在 \(\texttt{B}\) 前的最小操作次数。由于现在保证第 \(i\) 个 \(\texttt{A}\) 一定在第 \(\texttt{B}\) 前,那么将第 \(j+1\) 个 \(\texttt{A}\) 到第 \(i\) 个 \(\texttt{B}\) 的部分拿出来,发现可以分成五部分:一些排名在 \([j+1,i]\) 内的 \(\texttt{A}\)、一些排名 \(\le j\) 的 \(\texttt{B}\)、一些 \(\texttt{A}\) 和 \(\texttt{B}\)、一些排名 \(>i\) 的 \(\texttt{A}\) 以及一些排名在 \([j+1,i]\) 内的 \(\texttt{B}\)。发现实际上操作只在第三部分进行,那么每个 \(\texttt{A}\) 需要被操作的次数等于前面 \(\texttt{B}\) 的个数。
设 \(pre_i\) 表示第 \(i\) 个 \(\texttt{A}\) 前面 \(\texttt{B}\) 的个数,那么得到贡献函数 \(w(j,i)=\sum_{p=j+1}^i \max(pre_p-j,0)\),容易证明 \(w(j,i)\) 满足四边形不等式,可以 wqs 二分优化。
考虑如何优化内层 DP,首先是去掉取 \(\max\),设 \(pos_i\) 表示第一个 \(pre\ge i\) 的 \(\texttt{A}\),得到 \(w(j,i)=\sum_{p=pos_j}^i pre_p-j\)。记 \(pre_i\) 的前缀和 \(sum_i\),就化简成了 \(w(j,i)=sum_i-sum_{pos_j-1}+(i-pos_j+1)\times j\),可以斜率优化。
同样存在 \(pos_j>i\) 的情况不能拆成前缀和,这时贡献函数为 \(0\),而由于 \(pos_j\) 单调,在斜率优化时可以等到 \(\ge pos_j\) 的 \(i\) 出现再把 \(j\) 加入凸包,同时还要维护没有加入的 \(j\) 中 \(f_j\) 的最小值,可以单调队列。这样内层 DP 就做到线性。
参考资料
-
OI Wiki