学习笔记——wqs 二分
前言
概论
这类问题的特点是,本来不需要求代价,我却二分出一个代价从而间接的满足题目中的某些限制。最显著的标志,就是 ⌈恰好选 \(k\) 个⌋ 的限制。
这样说比较抽象,来看这题:
这题限制了白色边的数量。于是我们二分一个权值,把所有白边全部减去这个权值,然后做最小生成树。如果选出的白边过多,那么就减小这个权值,否则继续增大。
这种在某一类物品选取的时候额外的加上权值来限定它要恰好选几个的方式,就是 wqs 二分。
那么和 dp 有什么关系呢?
你看这题,如果是暴力 dp,可以令 \(dp_{i,j,k}\) 表示前 \(i\) 个用了 \(j\) 个『宝贝球』和 \(k\) 个『超级球』的最大期望。显然不够优秀。
但是我们可以二分一个权值,使得每次使用『宝贝球』会付出对应的代价,然后令 \(dp_{i,j}\) 表示前 \(i\) 个中,能用『宝贝球』就用,并且恰好用 \(j\) 个『超级球』的最大期望。并记得记录使用的『宝贝球』的个数。然后 wqs 二分就做完了。
也就是说,wqs 二分在 dp 中的用法还是比较有限的,当题目中需要限定某一个物品恰好选 \(k\) 次,那么我们可以无视这个限制,利用 wqs 二分来减少 dp 的维度。
条件
但是!并非所有的限定选 \(k\) 个问题都可以用 wqs 二分。也就是说 wqs 二分有条件。
这就需要我们来考虑 wqs 二分的本质了。
首先我们考虑对于原问题,我们令选 \(x\) 个的答案是 \(f(x)\),这样我们起初并不知道它长什么样子。然后我们二分了一个东西,加到 \(x\) 的权值。我们可以理解成一条斜率为我们二分的值 \(a\) 的直线。然后求答案的过程实际上就是用这条直线去切这个答案。为了满足二分的单调性,我们必须要满足这个答案构成了凸的形状。
也就是说,对于 \(\forall x,f(x)-f(x-1)\ge f(x+1)-f(x)\)。
习题
这里主要是优化 dp 的一些习题。
注意使用 wqs 二分最终答案要减去你二分的权值。不要撒敷敷的像我一样对着 AC 代码调了
没有加强的版本可以用四边形不等式做。然后看到这题就比较简单了。我们刚说过,对于 \(m\) 个邮局的限制,可以通过对邮局加权来实现。这样利用 wqs 二分就消去了 dp 的一维(凸性可以感性理解一下,就是前几个邮局加入的时候,对答案的贡献很大,越多之后,再加入的邮局显得没啥用了,所以是一个下凸包)。
现在我们根据之前做原版时的经验,这东西是可以用 1D1D 转移的四边形不等式来优化的,所以二分+单调队列就做完了。
又是这个恰好 \(m\) 段。于是 wqs 二分掉一维。但是我们需要分析它的凸性。首先把式子里的平均数去掉,也就是能转化成这个样子:
也就是每一段的和,每一段的和的平方再加一。对于每一段的和,最后加起来都是一样的,所以最终有影响的就是这个 \(1\) 和平方项。考虑分的段数越多,再多分一段对它的影响。由于平方项所含的项数随着段数增加已经减少了,所以分的段数越多,每多分一段答案的减少量就减少,所以是一个下凸的函数。
所以二分每分出一段的代价,利用斜率优化每次 \(O(n)\) 检查即可。
尤其注意二分的值域是否够大。
恰好 \(k\) 轮,直接上 wqs 二分(别急,考虑凸性)。
内部直接斜率优化一下就行了,这题是上凸包。
问题转化成从树中选出 \(k+1\) 条点不相交的链,求链权值和最大。恰好 \(k+1\),看起来就是很 wqs 二分的。考虑凸性。分的链越多,再增加一条对最终总收益的影响就越小,所以是上凸的。
然后内部验算的时候,用树形 dp 容易做到 \(O(n)\)。具体地,是令 \(dp_{i,0/1/2}\) 表示以 \(i\) 为根的子树中,节点 \(i\) 不在链上/是链的端点/在链的中部。然后直接转移即可。对于 \(dp_{i,0}\),直接取每个儿子的最大值即可,\(dp_{i,1}\) 则取一个儿子的 \(dp_{s,1}+w\),\(dp_{i,2}\) 则取两个儿子的 \(dp_{s,1}\),直接利用差值取前两个即可。然后我们还要记录当前子树每种状态下分的确定的链的条数。
结语
选用的例题还是比较少的,其中林克卡特树这题的套路应该是会见得比较多。就是如果在 dp 的时候这个次数不好记录,可以开一个结构体来存。然后注意二分的边界,一般可以设 \(nv\) 大小的,但是如果说题目有卡这一点的话还是精确计算比较保险。
剩下的还是考察 dp 基本功。