WQS二分

$Part$ $1$ $Introduce:$

最小限度生成树

问题描述:给定 $n$ 个点 $m$ 条边 的无向图,再给定点 $s$,常数$k$,求点 $s$ 至少连 $k$ 条边的最小生成树的边权和。
感觉没什么思路,看上去暴力也并不是很好写。
考虑最小生成树的流程,我们发现,如果所有与 $s$ 相连的边的边权值小于不与 $s$ 相连的边,我们肯定会选到 $n - 1$ 条与 $s$ 相连的边。同理,当所有与 $s$ 相连的边的边权值大于不与 $s$ 相连的边,我们一条也不会选。这启发我们可以给每条与 $s$ 相连的边增加一个权重,当权重为一定大小时恰好可以选 $k$ 条边。
但是决定增加多少权重呢?我们令 $f(w)$ 为权重为 $w$ 时,选择与 $s$ 相连的边的数量。可以发现当
$$\lim_{w\to-\infty}f(w)=n-1$$

$$\lim_{w\to\infty}f(w)=0$$
而且易知(见后文)这是单调不增的,所以我们可以采取二分来确定合适的 $w$。

$Part$ $2$ $Proof:$

实际上,我们令与 $s$ 相连的边为白边,其余则是黑边。 设 $g(x)$ 为选择 $x$ 条白边时的最小生成树边权和,画出 $g(x)$ 的图像可知这是下凹函数。 转自
设 $g(x)$ 的最低点为 $c$。我们想,在选择 $c$ 条白边前,$g(x)$ 是单调递减的,超过 $c$ 条后,是单调递增的。同时又有:$\forall x_1 < x_2 < x_3,k_1 = \frac{g(x_2)-g(x_1)}{x_2-x_1} \le k_2 = \frac{g(x_3)-g(x_2)}{x_3-x_2}$ 即,斜率是单调的。
考虑怎么利用这个性质, 我们知道对于每一个斜率,有唯一一条斜率相同的直线与下凹函数相切。对于此题,斜率越小,切点横坐标越前,反之越后。因而我们可以尝试二分这个斜率,来尝试得到这个切点,假设我们能够求得对应的 $x$ 及 $f(x)$,我们就可以确定下一步二分的斜率应该更大还是更小,并得到对应的最小值。 下凹函数有一个性质:对于同一斜率 $k$ 的直线过函数上一点,过切点的直线的纵轴截距最小。 (同上)
所以我们可以令 $h(x) = f(x) - kx$ 来表示该截距。它的实际意义为:
选取 $x$ 条白边时,所有白边都减去 $k$ 所得到的最小值。 引出一个性质:切点上的 $h(x)$ 为每一条白边价值减去 $k$ 后,不限制白边数量选取得到的全局最优解。
$proof$:
对于任意一点 $(x,f(x))$,对应的是选取恰好 $x$ 个白边时对应的最优解,加入我们将所有边的边权都减少 $k$,显然任意两条边之间的相对大小关系是不变的,那么选择的边集并不会改变,于是这个最优解就变为了 $f(x)- kx$,也就是 $h(x)$,也就是直线的纵轴截距;而根据我们上面提到的下凸壳的性质,我们可以知道,过切点 $(a,f(a))$ 的直线的纵轴截距一定是所有截距中最小的,也就是所有 $g(x)$ 中最小的,于是也就是不加限制选择白边的最优解,注意得到该最优解需要选出的白边数量一定是 $a$,而加上 $k⋅a$ 得到的就是 $f(a)$.(同上,引自$Dfkuaid$大佬)
这就是我们一开始这么做为什么是对的, 而这种思想叫做 $WQS$ 二分。
形式化的:给定一些带有价值的物品,价值可以为负,对于物品的选择具有一定限制,求选定物品总价值最大/最小值。
往往这类题目的价值函数为上凸/下凹函数。 且不限制选的个数,很容易求解。

$Part$ $3$ $Application$ :

$T1:$
给定 $n$ 个点,每个点有一个权值,要求选取 $k$ 个点,使得代价和最大/最小,且不允许选取相邻的点。
$1 \le n \le 5\times 10^5$
我们先考虑最大值。有一个很显然的 $O(nk)$ 做法。设 $f_{i,j}$ 为当前在第 $i$ 个点,已经选了 $j$ 个点的最大贡献。有:
$$f_{i,j} = \max \left \{ f_{i-1,j},f_{i-2,j-1}+a_i\right \}$$
考虑怎么优化它,我们发现当除去 $k$ 的限制之后,我们可以 $O(n)$ 来转移这个方程。于是我们考虑怎么把复杂度中的 $k$ 去掉。我们想到 $WQS$,它主要运用在凹函数上,我们只要确定它是不是凹函数就行了。当 $k$ 小于一个值 $c$ 时,$k$ 越大代价和越高,当超过 $c$ 时,我们必须选择一些负值点,或者要把原来的点删掉而选择两个相邻的点,所以代价和会逐渐减少。据此,我们感性理解了它是一个下凹函数。要使用 $WQS$ 二分,我们得思考它斜率的意义是什么。在这题,斜率的意义是每个选择的点都减去 $w$。当 $w$ 越大,选到的点越少,$w$ 越小,选到的点越多。到这里,我们做出了这道题。

原题(最大值) 参考code

最小值 code

$In$ $fact$,这道题也可以使用反悔贪心来做(待补)。

$T2:$
给你一个序列,要求你分成 $m$ 段,每一段的贡献都为下式,求最小贡献和。$$\frac{((\sum_{i=1}^{n}x_i \times \overline{x} ) + \overline{x})^2}{\overline{x}^2} $$
将原式化简可得 $(\sum x_i + 1)^2$
所以不加限制 $m$ 的转移方程为:
$$f_i=\min_{j < i} \left \{ f_j+(\sum_{k=j+1}^{i}x_k+1)^2\right \}$$
使用斜率优化,转移复杂度为 $O(n)$。
考虑使用 $WQS$ 二分来限制 $m$ ,我们给选择的每一段都加上二分的值 $w$。
注意 $check$ 函数中斜率优化的写法

bool check(ll x) {
    to = tl = 1;
    for(int i = 1;i <= n;i++) {
        while(to < tl && K(q[to], q[to + 1]) <= 2 * s[i]) to++; // attention
        f[i] = f[q[to]] + pow(s[i] - X(q[to]), 2) + x;
        g[i] = g[q[to]] + 1;
        while(to < tl && K(q[tl - 1], i) < K(q[tl - 1], q[tl])) tl--;
        q[++tl] = i;
    }
    return g[n] >= m;
}

因为在斜率相同时,我们尽量选择靠右的点,在弹出队列要注意取等。

posted @ 2023-10-03 20:21  Saka_Noa  阅读(12)  评论(0)    收藏  举报  来源