CF1110F Nearest Leaf

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

考虑先把问题离线下来,

用线段树维护当前点到所有叶子的最近距离

如果 u u u进入一颗子树 v v v,那么就把 v v v对应的区间全部 − 1 -1 1,区间外的全部 + 1 +1 +1

于是线段树维护区间 + − 1 +-1 +1即可

#include<bits/stdc++.h>
#define N 500050
#define ll long long
#define ls (rt << 1)
#define rs (rt << 1 | 1)
using namespace std;
struct E {
    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 ++;
}
const ll inf = 2e18;
ll mi[N << 2], tg[N << 2], dep[N], ans[N];
int size[N], n, m;
void padd(int rt, ll o) {
    if(mi[rt] != inf) mi[rt] += o;
    tg[rt] += o;
}
void pushdown(int rt) {
    if(tg[rt]) {
        padd(ls, tg[rt]), padd(rs, tg[rt]);
        tg[rt] = 0;
    }
}
void update(int rt) {
    mi[rt] = min(mi[ls], mi[rs]);
}
void build(int rt, int l, int r) {
    if(l == r) {
        if(size[l] == 1) mi[rt] = dep[l];
        else mi[rt] = inf;
        return ;
    }
    int mid = (l + r) >> 1;
    build(ls, l, mid), build(rs, mid + 1, r);
    update(rt);
}
void add(int rt, int l, int r, int L, int R, int o) {
    if(L > R) return ;
    if(L <= l && r <= R) {
        padd(rt, o);
        return ;
    }
    pushdown(rt);
    int mid = (l + r) >> 1;
    if(L <= mid) add(ls, l, mid, L, R, o);
    if(R > mid) add(rs, mid + 1, r, L, R, o);
    update(rt);
}
ll query(int rt, int l, int r, int L, int R) {
    if(L <= l && r <= R) return mi[rt];
    pushdown(rt);
    int mid = (l + r) >> 1;ll  ret = inf;
    if(L <= mid) ret = query(ls, l, mid, L, R);
    if(R > mid) ret = min(ret, query(rs, mid + 1, r, L, R));
    return ret;
}
void Dbug(int rt, int l, int r) {
    if(l == r) {
        printf("%lld ", mi[rt]);
        return ;
    }
    int mid = (l + r) >> 1;
    pushdown(rt);
    Dbug(ls, l, mid), Dbug(rs, mid + 1, r);
}
struct Q {
    int l, r, id;
};
vector<Q> q[N];
void dfs(int u, int fa) {
    size[u] = 1;
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v, c = e[i].c;
        if(v == fa) continue;
        dep[v] = dep[u] + c;
        dfs(v, u); size[u] += size[v];
    } 
}
void dfss(int u, int fa) {
   // Dbug(1, 1, n); printf("    *%d \n", u);
    for(int i = 0; i < q[u].size(); i ++) {
        int l = q[u][i].l, r = q[u][i].r, id = q[u][i].id;
        ans[id] = query(1, 1, n, l, r);
    }

    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v, c = e[i].c;
        if(v == fa) continue;
        add(1, 1, n, v, v + size[v] - 1, -c);
        add(1, 1, n, 1, v - 1, c);
        add(1, 1, n, v + size[v], n, c);
        dfss(v, u);
        add(1, 1, n, v, v + size[v] - 1, c);
        add(1, 1, n, 1, v - 1, -c);
        add(1, 1, n, v + size[v], n, -c);
    }
}
int main() {
    scanf("%d%d", &n, &m);
    init();
    for(int i = 2; i <= n; i ++) {
        int fa, c;
        scanf("%d%d", &fa, &c);
        insert(i, fa, c), insert(fa, i, c);
    } 
    
    for(int i = 1; i <= m; i ++) {
        int x, l, r;
        scanf("%d%d%d", &x, &l, &r);
        q[x].push_back((Q){l, r, i});
    }

    dfs(1, 1);
    build(1, 1, n);
    dfss(1, 1);
    for(int i = 1; i <= m; i ++) printf("%lld\n", ans[i]);
    return 0;
}
posted @ 2021-12-04 08:09  lahlah  阅读(25)  评论(0编辑  收藏  举报