可以把操作离线,每次开始遍历到一个节点,把以它为根的操作加上,结束时把这个点的操作删去。
因为是(dfs),所以一个点对同一深度的贡献是一定的,可以用树状数组区间加减,求前缀和。
但是因为是(dfs),完全可以把前缀和传入,就不需要树状数组了。
#define B cout << "BreakPoint" << endl;
#define O(x) cout << #x << " " << x << endl;
#define O_(x) cout << #x << " " << x << " ";
#define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#define LL long long
const int inf = 1e9 + 9;
const int N = 6e5 + 5;
using namespace std;
inline int read() {
int s = 0,w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-')
w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * w;
}
int head[N],to[N],nxt[N],cnt;
void add(int x,int y) {
to[++cnt] = y;
nxt[cnt] = head[x];
head[x] = cnt;
}
int n,m;
struct node {
int d,x;
inline node() {}
inline node(int __d, int __x) :d(__d), x(__x){}
};
vector<node> s[N];
LL c[N],ans[N];
void dfs(int u,int fa,int dep,LL sum) {
for(auto it = s[u].begin();it != s[u].end();it++) {
c[dep] += it->x;
if(dep + it->d + 1 <= n) c[dep + it->d + 1] -= it->x;
}
sum += c[dep],ans[u] = sum;
for(int i = head[u];i;i = nxt[i]) {
int v = to[i];
if(v != fa) dfs(v,u,dep + 1,sum);
}
for(auto it = s[u].begin();it != s[u].end();it++) {
c[dep] -= it -> x;
if(dep + it -> d + 1 <= n) c[dep + it -> d + 1] += it -> x;
}
}
int main() {
n = read();
for(int i = 1;i < n;i++) {
int x = read(),y = read();
add(x,y),add(y,x);
}
m = read();
for(int i = 1;i <= m;i++) {
int v = read(),d = read(),x = read();
s[v].push_back(node(d,x));
}
dfs(1,0,0,0);
for(int i = 1;i <= n;i++) printf("%lld ", ans[i]);
return 0;
}