带权二分-一丢丢感悟

问题:边界条件的考虑方式,权值相等时,第二关键字应该是最大化还是最小化。

用 hzwer 的选 \(k\) 个白点那道题来说吧,给每个白点增加 \(mid\) 的权值,计算 MST 的白点数量 \(cnt\)

\(mid\) 增大, \(cnt\) 减小,二分大概长这样:

    while (l <= r) {
        cnt = check(mid);
        if (cnt <= k) {
            // update ans
            r = mid - 1;
        } else {
            l = mid + 1;
        }
    }

类似一个单调不升的序列,二分一个值,最后肯定是停在一段连续相同的值的左边(因为 \(cnt = k\) 的时候还在减小 \(mid\) )。

如此能保证的只有 \(mid - 1\) 位置的 \(cnt > k\) ,它是非法的。

这种非法情况,应该无论如何都非法。就是说 \(mid - 1\) 位置对应的各种 \(cnt_{min}, \cdots, cnt_{max}\) ,都大于 \(k\) (否则合法的情况就可能在 \(mid - 1\) 位置,这时候该选 \(mid\) 还是 \(mid - 1\) 就说不清了),所以应该保证 \(cnt_{min}>k\) 才正确。

说完了。

具体放到题里面,求 \(cnt\) 时,点权相同时,最小化 \(cnt\) 。反过来说有人二分里面更新答案时用的是 cnt >= k , 那就应该优先选白点,计算 \(cnt_{max}\)

似乎大佬们有不同的解释,不过暂时我只能这样理解,似乎没什么问题。八省联考 2018 林克卡特树 也是这个方式考虑第二关键字。

update (2019.03.27) : 更简单的理解方法是,原函数加一个一次函数等价与导数加一个常数,也就是向上平移。每次求得的是导数与 \(x\) 轴交点。导数有时平行于 \(x\) 轴就需要上面说的方法解决了。

posted @ 2019-02-22 19:58  derchg  阅读(243)  评论(0编辑  收藏  举报