CF - 1110F Nearest Leaf
题解:
先用题目给定的dfs方式得到dfs序,记录下出入的dfs序。
很明显可以得知的是,以u为根的子树的dfs序在 in[u] - out[u] 的范围之内。
将每个询问先全部存到对应的节点上。
然后我们以1为root,先求出每个叶子节点到1的距离。
对1的询问查询更新完答案之后。
(假设1和2之间有一条权值为w的边)
那么以2为根的话,就相当于是 in[2] --- out[2] 区间里面的所有值的距离 -= w, 其他点的距离 += w。
然后对于每个点都这样处理。
注意修改和还原更新。
代码:
/* code by: zstu wxk time: 2019/02/09 */ #include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 5e5 + 100; vector<pll> vc[N]; int in[N], out[N], tot; LL a[N]; int n, q; void dfs(int u, LL ct){ in[u] = ++tot; if(vc[u].size()) a[tot] = INF; else a[tot] = ct; for(pll p : vc[u]){ dfs(p.fi, ct+p.se); } out[u] = tot; } LL Mn[N<<2], lz[N<<2]; void PushUp(int rt){ Mn[rt] = min(Mn[rt<<1], Mn[rt<<1|1]); } void PushDown(int rt){ if(lz[rt]){ lz[rt<<1] += lz[rt]; lz[rt<<1|1] += lz[rt]; Mn[rt<<1] += lz[rt]; Mn[rt<<1|1] += lz[rt]; lz[rt] = 0; } return ; } void Build(int l, int r, int rt){ if(l == r){ Mn[rt] = a[l]; return ; } int m = l+r >> 1; Build(lson); Build(rson); PushUp(rt); return ; } void Updata(int L, int R, LL C, int l, int r, int rt){ if(L <= l && r <= R){ lz[rt] += C; Mn[rt] += C; return ; } PushDown(rt); int m = l+r >> 1; if(L <= m) Updata(L, R, C, lson); if(m < R) Updata(L, R, C, rson); PushUp(rt); return ; } LL Query(int L, int R, int l, int r, int rt){ if(L <= l && r <= R){ return Mn[rt]; } PushDown(rt); int m = l+r >> 1; LL ret = INF; if(L <= m) ret = Query(L, R, lson); if(m < R) ret = min(ret, Query(L, R, rson)); return ret; } #define mp make_pair vector<pair<pll,int>> Q[N]; LL ans[N]; void Dfs(int u, int ct){ Updata(1, n, ct, 1, n, 1); Updata(in[u], out[u], -2*ct, 1, n, 1); for(auto x : Q[u]){ ans[x.se] = Query(x.fi.fi, x.fi.se, 1, n, 1); } for(pll x : vc[u]){ Dfs(x.fi, x.se); } Updata(1, n, -ct, 1, n, 1); Updata(in[u], out[u], 2*ct, 1, n, 1); return ; } void Ac(){ for(int i = 2, v, w; i <= n; ++i){ scanf("%d%d", &v, &w); vc[v].pb({i,w}); } dfs(1, 0); Build(1, n, 1); for(int i = 1,u,l,r; i <= q; ++i){ scanf("%d%d%d", &u, &l, &r); Q[u].pb(mp(mp(l,r),i)); } Dfs(1, 0); for(int i = 1; i <= q; ++i) printf("%I64d\n", ans[i]); } int main(){ while(~scanf("%d%d", &n, &q)){ Ac(); } return 0; }