wqs二分

wqs二分

先有一个神秘函数 \(f\),因为有一些神秘限制导致我们无法直接算出它在 \(x\) 处的取值 \(f(x)\).

通过人类智慧,我们发现 \(f\) 是一个凸函数(斜率单增)。 \(f\) 之所以难求,是因为有一些神秘限制。 例如需要取 a 个数。设 g 代表可以取任意多个数,并且 g 是好求的。通过计算发现我们求出的 g(x) 刚好选了 a 个数,那么 g 就是我们要就的 f 。(注意,我们不需要 f 在每一个位置的答案,只要知道在 x 处的取值即可)。当然,大多数情况下,我们求出的 g(x) 不会刚好选了 a 个数。假设现在选多了,可以考虑让 g 在每次选择数的时候会产生一个额外的权值 k,这时候,计算 g 的时候会倾向于少选一些数。选少了同理(事实上,只有当 f 是凸函数的时候,才能保证能正确性)。我们通过调整额外的权值 k(二分),可以找到 g 刚好选择了 k 个数的那个时刻。g 会比 f 多出 ak 的额外贡献,那么 \(f(x) = g(x) - ak\).

例题1 P2619【国家集训队2】Tree I.

题意:一张分白边和黑边的图,求满足白边数量为 K 生成树中最小的。

\(f(\text该树)\) 表示选 K 条白边的最小生成树代价。 \(g(\)该树\()\) 代表没有限制的最小生成树。

由于直接跑 g 会导致选的白边过多/少,我们可以对每一条白边权值加上 x 。调整 x 的大小,直到选到的白边数量等于 k.

有一个细节:Kruskal 算法瓶颈在于排序。对于排序,如果每轮对某些数都加上一个相同的 k ,发现加 k 的这些数的相对位置没变,所以用归并排序可减少一个 log。这个题同理。所以总复杂度是一个 log

例题2 P5633最小度限制生成树.

求最小的生成树使点 s 度数为 K。

和上一题几乎一样。认为与 s 所连的边为白边,其他边是黑边。

例题3 [AT_arc168_e ARC168E] Subsegments with Large Sums.

给定长度为 n 的数列 {\(a_i\)} 和两个参数 k,s,求将 {\(a_i\)} 划分成 k 段,最大化和 ≥s 的段数。

看到分成 k 段,想到 wqs二分。然后发现原函数不是凸的(具体我也不太明白)。二分答案 x 。现在要选出 x 段大于 s 的段,然后使得总段数大于 k。考虑再转化。显然每一段长度之和为 n,于是有:

\[\sum (r-l+1) = n \]

把 1 提出来:

\[\sum (r-l) \le n - k \]

显然令小于 s 的那些段长度为 1 时最优。所以可以只累加大于 s 的那 x 段。

现在的问题变成了刚好分 x 段大于 s 的,要 \(\sum r-l\) 的最大值大于等于 n - k。

设 f 是刚好 x 段(枚举上界固定是 x)的最小值,g 是没有限制的最小值。把 g 的 $\sum r-l $ 改成 \(\sum r- l + v\),v 就是那个附加值。v 比较大的时候,g 会倾向于少选一些区间,也就是一次性选一个巨大的区间。求 g 的话就普通 dp 就行了。具体来说:\(g_{i}\) 是一个 pair 类,第一维是当前 \(\sum r- l + v\),第二维是目前选的段数的最大值(用最大值是应为如果段数多了,可以随便合并一些块)。因为 g 没有段数限制,所以不用给段数多开一维。转移的话就从第一个距离大于 s 的点转移。最后记得给 g 减去 kv。

posted @ 2025-03-24 19:29  花子の水晶植轮daisuki  阅读(14)  评论(0)    收藏  举报
https://blog-static.cnblogs.com/files/zouwangblog/mouse-click.js