題目鏈接:Codeforces - Vasya and a Tree
如果是簡單的子樹加減,那麼直接dfs序+Fenwick就可以解決。
現在,子樹加上了一個深度的限制。我們似乎可以從上到下,用主席樹合併答案。實際上也是可以的。
但是我們有一個簡單的做法,就是利用dfs,每次進入子樹的時候維護Fenwick,出子樹的時候清除影響,就利用小空間達到和主席樹一樣的效果了。
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10;
int n,m,res[N],d[N],dep[N];
vector<int> g[N]; vector<pair<int,int>> v[N];
inline void add(int a,int b){g[a].push_back(b),g[b].push_back(a);}
inline void insert(int x,int v){for(;x<=n;x+=x&(-x)) d[x]+=v;}
inline int ask(int x){int s=0; for(;x;x-=x&(-x)) s+=d[x]; return s;}
void dfs(int x,int fa){
dep[x]=dep[fa]+1;
for(auto to:v[x]) insert(dep[x],to.second),insert(dep[x]+to.first+1,-to.second);
res[x]=ask(dep[x]);
for(auto to:g[x]) if(to!=fa) dfs(to,x);
for(auto to:v[x]) insert(dep[x],-to.second),insert(dep[x]+to.first+1,to.second);
}
signed main(){
cin>>n;
for(int i=1,x,y;i<n;i++) scanf("%lld %lld",&x,&y),add(x,y);
cin>>m;
for(int i=1,p,d,x;i<=m;i++) scanf("%lld %lld %lld",&p,&d,&x),v[p].push_back({d,x});
dfs(1,1);
for(int i=1;i<=n;i++) printf("%lld ",res[i]);
return 0;
}