2020-2021:teams:farmer_john:jjleo:wqs二分
WQS二分
wqs二分可以解决形如在$n$个物品中选$k$个物品最大化/最小化总价值。直接dp一般是$O(nk)$的,而如果题目满足下面的条件并且可以用$O(n)$时间在不考虑选择物品个数的情况下计算出最大值/最小值,就可以用wqs二分做到$O(n \log n)$。
以最大化价值为例,设$x$表示选择物品的个数,设$f(x)$表示选$x$个物品的最大值,如果$f(x)$关于$x$是凸函数或凹函数,那么图象就是一个凸包。虽然我们不知道具体凸包长什么样,但是我们可以利用凸包的性质,通过二分直线的斜率使得这条直线与$(k,f(k))$这个点“相切”,从而间接得到$f(k)$的值。
以凸函数为例,由于图像是一个凸包,所以一条直线,如果想让直线与图象有交点的情况下截距最大,那么直线一定恰好经过凸包上的一个点,此时我们通过下面的方法求出这个点后,如果这个点的横坐标$<k$,那么减少斜率,否则增大斜率。
设直线为斜率为$mid$,直线方程即为$y = mid \times x + b$那么截距为$y - mid \times x$,当直线经过每个点时截距为$f(x) - mid \times x$,设经过$z$时截距最大,那么$\max\{f(x) - mid \times x\} = f(z) - mid \times z$。也就是说如果给每个物品的价值减少$mid$,那么最大化价值时选择的物品数就是$z$,此时不用考虑需要选择的物品数,只需要记录每个状态选择了几个物品即可,一般通过一次dp即可获得结果。假设最后得到的斜率为$l$,此时最大截距为$b$,那么答案即为$b + l * k$。
需要注意,一般题目中的$f(x)$可能并不是严格凸或者严格凹,因此可能出现连续的点对应斜率相同,二分的时候要注意边界问题。
可以开一个结构体记录dp状态的最大值以及取得此时最大值的选取物品数,大幅简化代码编写的复杂度。
CF739E
林克卡特树
Tree I
CF1279F
2020-2021/teams/farmer_john/jjleo/wqs二分.txt · 最后更改: 2020/06/25 23:07 由 jjleo