wqs 二分
这个东西稍微有点神秘的。
这个东西的应用场景一般是,你有一个 DP,然后这个 DP 值关于某一维是凸的,通常这一维的含义都是使用了多少个元素。
然后因为最终这个东西是一个凸函数,并且我们只需要其中一个地方的值,那我们把所有值全都计算出来显然是浪费的。我们的另一个想法就是用一个斜率的直线去切这个凸包,如果我们可以求出这个直线跟这个凸包的交点,我们去比较这个交点到底在目标位置的哪侧,然后相应调整我们的斜率去逼近这个位置,直到我们真正到达这个目标点为止。
然后因为这个维度通常都是多少个元素,所以我们可以给每个元素带一个额外代价,然后 DP 一次就行了。为了知道这个交点的位置,我们通常维护在取到最大值的同时,最少用几个元素。当然,最好还是最少最多都维护一下。
当然,这里会出现一个问题。因为凸包上可以有斜率相同的若干个点连到一起,这时如果你的斜率也是这个值,你到底交到哪个位置?所以我们有两种处理手段,一种是维护最小最大值,然后当它们包住询问位置的时候计算答案。另一种是只维护最小值,然后如果它比较小尝试变大,否则只能变小。然后也是二分一个最接近的位置出来,显然这个就是答案。
其实上面的这个思考过程有一个不连续的部分,就是凭啥你一看到一个凸函数单点求值上来直接就是二分斜率。而且说实在的,你能快速求出这个斜率的切点是很奇怪的一件事,如果不是见过了,很难往这个方向去想。
然后这里还有一个问题,就是构造方案。因为可能有共线情况,所以你固然能求出来一个方案,但是这个方案往往是最小/最大对应的方案,你想求一个恰好的方案是困难的。一个做法是微扰,强行让它们不共线。但是这个一看就比较玄学。
哦有一个人说了一个构造方法,还挺对的。link。
就是我们在内层 DP 的时候,对每个前缀位置,同时维护达到这个最小值需要的 \(mn/mx\),然后构造方案的话,我们就找上一个满足 \(X-1\in [mn_j,mx_j]\) 的位置就可以构造出来了。
那这样的话,只维护最小值应该也有类似做法,我们找最大的一个满足 \(X-1\ge mn_j\) 的 \(j\) 就行了。
但问题是,有一类内层问题并不需要 DP 解决,这时怎么办呢?这个是不是得具体分析一下啥的。
还有一点没说透的地方。

浙公网安备 33010602011771号