CF516D Drazil and Morning Exercise

https://www.luogu.com.cn/problem/CF516D

注意到 min ⁡ f x \min f_x minfx的一定是在直径上
以这个点为根,可以得到一个 f f f随深度递增的树
直接树上差分,找最大的即可

code:


#include<bits/stdc++.h>
#define N 400050
#define ll long long
using namespace std;
struct edge {
    int v, c, nxt;
} e[N << 1];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v, int c) {
    e[eid].v = v;
    e[eid].c = c;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}
ll d[N], dd[N], dis[N], sta[N];
int top, stb[N], s[N], q, n;
void dfs(int u, int fa) {
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v, c = e[i].c;
        if(v == fa) continue;
        //printf(" %d %d  %d\n", u, v, c);
        d[v] = d[u] + c; dfs(v, u);
    }
}
void dfss(int u, int fa) {
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v, c = e[i].c;
        if(v == fa) continue;
        dd[v] = dd[u] + c; dfss(v, u);
    }
}
void dfs1(int u, int fa, ll x) {
    s[u] ++, sta[++ top] = dis[u], stb[top] = u;
    int pos = lower_bound(sta + 1, sta + 1 + top, dis[u] - x) - sta - 1;
    s[stb[pos]] --;
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v, c = e[i].c;
        if(v == fa) continue;
        dfs1(v, u, x); s[u] += s[v];
    }
    top --;
}
int main() {
    init();
    scanf("%d", &n);
    for(int i = 1; i < n; i ++) {
        int u, v, c;
        scanf("%d%d%d", &u, &v, &c);
        insert(u, v, c), insert(v, u, c);
    }

    int S = 1, T = 1;
    d[S] = 0; dfs(S, S);
    for(int i = 1; i <= n; i ++) if(d[S] < d[i]) S = i;
    //for(int i = 1; i <= n; i ++) printf("%lld ", d[i]); printf("     %d\n", S);
    
    d[S] = 0; dfs(S, S);
    for(int i = 1; i <= n; i ++) if(d[T] < d[i]) T = i;

   // for(int i = 1; i <= n; i ++) printf("%lld ", d[i]); printf("     %d\n", T);
    

    dd[T] = 0; dfss(T, T);
    for(int i = 1; i <= n; i ++) dis[i] = max(d[i], dd[i]);

    int rt = 1;
    for(int i = 1; i <= n; i ++) if(dis[i] < dis[rt]) rt = i;
    // printf("\n");
    // for(int i = 1; i <= n; i ++) printf("%lld ", dis[i]); printf("     %d\n", rt);
    sta[++ top] = 0; stb[top] = 0;
    scanf("%d", &q);
    while(q --) {
        ll x;
        scanf("%lld", &x);
        dfs1(rt, rt, x);
        int ans = 0;
        for(int i = 1; i <= n; i ++) ans = max(ans, s[i]), s[i] = 0;
        printf("%d\n", ans);
    }
    return 0;
}
posted @ 2021-12-10 10:48  lahlah  阅读(60)  评论(0编辑  收藏  举报