关于二分的初始值

P4383 [八省联考 2018] 林克卡特树

Dyd本人 @ 2022-06-05 21:57:44

先发 AC 代码:

#include <bits/stdc++.h>
using LL = long long;
const int N = 3e5 + 100;
const int inf = 0x3f3f3f3f;
const LL INF = 1e18;
int n, num, l, r, mid;
struct Edge{ int ne, ver, w; } e[N << 1];
int h[N], idx = 0;
struct DP
{
    LL v; int num;
    bool operator < (DP x) const { return v == x.v ? num > x.num : v < x.v; }
    DP operator + (DP x){ return {v + x.v, num + x.num}; }
} d[N][3], as, td[3];
LL ans;
void add(int x, int y, int z){ e[idx] = {h[x], y, z}, h[x] = idx++; }
template<typename T>
bool cmx(T &x, T y){ return x < y ? x = y, true : false; }
void dp(int x, int fa)
{
    for (int i = h[x], y; ~i; i = e[i].ne) if ((y = e[i].ver) != fa)
    {
        dp(y, x);
        for (int j = 0; j <= 2; ++j) td[j] = {-INF, inf};
        for (int j = 0; j <= 2; ++j)
            for (int k = 0; k <= 2; ++k) cmx(td[j], d[x][j] + d[y][k]);
        cmx(td[1], d[x][0] + d[y][0] + DP{e[i].w - mid, 1});
        cmx(td[1], d[x][0] + d[y][1] + DP{e[i].w, 0});
        cmx(td[2], d[x][1] + d[y][0] + DP{e[i].w, 0});
        cmx(td[2], d[x][1] + d[y][1] + DP{e[i].w + mid, -1});
        for (int j = 0; j <= 2; ++j) d[x][j] = td[j];
    }
}
int main()
{
    scanf("%d %d", &n, &num);
    memset(h + 1, -1, n << 2);
    for (int i = 1, u, v, w; i < n; ++i)
    {
        scanf("%d %d %d", &u, &v, &w);
        add(u, v, w), add(v, u, w);
    }
    l = -1e12, r = 1e12;
    while (l <= r)
    {
        mid = (l + r) >> 1;
        for (int i = 1; i <= n; ++i)
        {
            d[i][0] = {0, 0};
            d[i][1] = {-INF, inf};
            d[i][2] = {-mid, 1};
        }
        dp(1, 0);
        as = d[1][0], cmx(as, d[1][1]), cmx(as, d[1][2]);
        if (as.num <= num + 1)
        {
            ans = as.v + LL(mid) * (num + 1);
            r = mid - 1;
        }
        else l = mid + 1;
    }
    printf("%lld\n", ans);
    return 0;
}

43 行如果写成 l = -1e6, r = 1e6 就会 WA 成 40pts

所以蒟蒻想问问:为啥 l, r 要定那么大?(或者说,wqs 二分如何确定 l, r 初始值该定多大?)


by Alex_Wei @ 2022-06-05 22:15:56

初始值定成斜率最大值和最小值啊


by Alex_Wei @ 2022-06-05 22:17:03

比如说,如果 f(x) 是上凸的,然后 x 的范围是 [0, n],那么 r 应该等于 f(1) - f(0) 的最大可能值,l 同理等于 f(n) - f(n - 1) 的最小可能值。


by Alex_Wei @ 2022-06-05 22:18:24

对于本题而言,因为 f(1) - f(0) 的最大可能值是 \mathcal{O}(nv) 的,所以你开 1e6 就要寄了。


by Alex_Wei @ 2022-06-05 22:19:53

比如构造一个点连三条长度为 \dfrac n 3 个点的链,这样 f(0) 只能选中两条,f(1) 可以选中另外一条,delta 是点数 \dfrac n 3 乘以边长。


by Alex_Wei @ 2022-06-05 22:20:47

@Dyd本人 还有这个标题应该写 wqs 二分罢,基础的二分和 wqs 二分差了可不是一点半点。


by Alex_Wei @ 2022-06-05 22:21:40

实际上一般来说 l, r 的初值设为 nv 比较保险,但如果为了卡常是可以仔细分析这个界的,具体题目具体对待。


by Dyd本人 @ 2022-06-06 08:39:17

@Alex_Wei 谢谢巨佬,我悟了!


|