ARC 116 E 题解

题目大意很简单,同时显然看出单调性,直接二分答案,问题变为给定最远覆盖距离,求最少覆盖点。

这是一个经典的贪心问题。事实上,他很简单。

我们提取并形式化题目:

  • 给定一棵树和值 \(k\),选取 \(s\) 个点涂黑。
  • 对于每一个点,如果离他最近的颜色为黑的点,与他的距离,小于等于 \(k\),我们认为这个点“被覆盖”。
  • 黑点显然被覆盖。
  • 求最少被涂黑的点。

他的贪心体现在,假设一个链很长,这个链的叶子节点和根的距离是最远的,那么这个叶子节点的至少第 \(k\) 级祖先需要被染色,同时,给恰好第 \(k\) 级祖先涂黑显然是最优的,因为这可以让这个祖先的子树全部被覆盖,好过任何其他方案。

所以枚举最深点到最浅点,如果枚举到没有被覆盖的点,就把他的 \(k\) 级祖先涂黑。这是贪心。

但事实上,我们需要更巧妙的方法来维护每一个点是否被覆盖、是否需要被涂黑。

我们假设 \(f_x\) 表示 \(x\) 到他的子树中最远的未被覆盖的点的距离,\(g_x\) 表示 \(x\) 到他的子树中最近的被涂黑的点。特殊的,如果 \(f_x = -inf\),表示 \(x\) 的子树被全部覆盖,\(g_x = inf\),表示 \(x\) 的子树都没被涂黑。

我们默认 \(f_x = -inf\),如果他没有被覆盖,我们会改变他。

分讨。

  • 如果 \(g_x > k\),表示 \(x\) 没有被覆盖,那么 \(f_x = \max(f_x, 0)\)
  • 如果 \(f_x + g_x <= k\),表示离 \(x\) 最近的黑点可以覆盖到离 \(x\) 最远的未被覆盖的点,这时 \(f_x = -inf\)
  • 如果 \(f_x = k\),那么 \(x\) 就必须被染色,所以令 \(f_x = -inf, g_x = 0\),同时将答案加 \(1\)

最后判断离 \(1\) 最远的未被覆盖的点与他的距离,如果大于等于 \(0\),则把答案加 \(1\)

代码。

#include<bits/stdc++.h>
#define int long long
using namespace std;
auto mread = [](){int x;scanf("%lld", &x);return x;};
const int N = 2e5 + 5;
int n = mread(), k = mread(), f[N], g[N], sum = 0;
vector<int> v[N];
void dfs(int x, int fa, int mid){
    f[x] = LONG_LONG_MIN, g[x] = 0x3f3f3f3f3f3f3f3f;
    for(int y : v[x]){
        if(y == fa){
            continue;
        }
        dfs(y, x, mid);
        f[x] = max(f[x], f[y] + 1);
        g[x] = min(g[x], g[y] + 1);
    }
    if(g[x] > mid){
        f[x] = max(0ll, f[x]);
    }
    if(f[x] + g[x] <= mid){
        f[x] = LONG_LONG_MIN;
    }
    if(f[x] == mid){
        f[x] = LONG_LONG_MIN;
        g[x] = 0;
        sum ++;
    }
    return;
}
int check(int mid){
    sum = 0;
    dfs(1, 1, mid);
    sum += (f[1] >= 0ll);
    return sum;
}
signed main(){
    for(int i = 1, x, y; i < n; i ++){
        x = mread(), y = mread();
        v[x].push_back(y);
        v[y].push_back(x);
    }
    int l = 0, r = n;
    while(l < r){
        int mid = l + r >> 1;
        if(check(mid) <= k){
            r = mid;
        }
        else{
            l = mid + 1;
        }
    }
    printf("%lld\n", l);
    return 0;
}
posted @ 2024-09-05 20:01  cndark_moon  阅读(26)  评论(0)    收藏  举报