wqs二分一般用于解决这样一种问题:
dp是凸函数,也就是多选一个物品,收获肯定更多
这种问题一般是有限制的,比如限制最多选择m个物品
且如果没有限制,将很容易计算
设
f
u
f_u
fu表示选 u 个的收获,图像如下:
我们要找到这样一个
(
m
,
f
m
)
(m,f_m)
(m,fm)
可以二分斜率 k ,得到斜率 k 的直线与图像相切的点,这个点相当于是截距最大的点,截距
g
u
=
f
u
−
k
∗
u
g_u=f_u-k*u
gu=fu−k∗u,相当于每个物品都减少 k 的价值,得到的最大的贡献点对应的x坐标,如果x大了意味着斜率小了,否则说明斜率大了,这样就能求出
f
m
f_m
fm了
P2619 [国家集训队]Tree I
设
f
i
f_i
fi表示至少有i个白边的最小生成树的权值
那么
f
i
f_i
fi一定是单调不减,可以给每个白边加一个值做最小生成树,二分这个值即可
CF739E Gosha is hunting
wqs二分套wqs二分
对两个维度分别二分,每次验证的时候进行一次dp,总时间复杂度
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n)
代码
这题还可以费用流,4000个点也不知道怎么跑过的
P4383 [八省联考 2018] 林克卡特树
考虑时间复杂度
O
(
n
k
)
O(nk)
O(nk)的树形dp
设
f
[
u
]
[
j
]
[
0
/
1
/
2
]
f[u][j][0/1/2]
f[u][j][0/1/2]表示dp到u节点,用了k个链,u节点使用的度数为0/1/2的最大值
那么我们很容易得到转移,60pts
容易发现k越大肯定会得到不劣的答案,所以可以使用wqs二分来优化
每次使用一个链就减去一个mid值,看看最大化答案需要的链的数量,如果大于要求的说明斜率mid小了,否则就是mid大了,可以二分解决
注意dp的时候维护的细节即可
代码