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;
}