思路:
dfs动态维护关于深度树状数组
返回时将当前节点的所有操作删除就能保证每次访问这个节点时只进行过根节点到当前节点这条路径上的操作
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 3e5 + 10; vector<int> g[N]; vector<pii> que[N]; LL bit[N], ans[N]; int n; void add(int x, int d) { while(x <= n) bit[x] += d, x += x&-x; } LL sum(int x) { LL ans = 0; while(x) ans += bit[x], x -= x&-x; return ans; } void dfs(int u, int o, int deep) { for (pii t : que[u]) { int d = t.fi; int x = t.se; int l = deep; int r = min(deep+d, n); add(l, x); add(r+1, -x); } ans[u] = sum(deep); for (int v : g[u]) { if(v != o) dfs(v, u, deep+1); } for (pii t : que[u]) { int d = t.fi; int x = t.se; int l = deep; int r = min(deep+d, n); add(l, -x); add(r+1, +x); } } int main() { int u, m, v, d, x; scanf("%d", &n); for (int i = 1; i < n; i++) { scanf("%d %d", &u, &v); g[u].pb(v); g[v].pb(u); } scanf("%d", &m); for (int i = 1; i <= m; i++) { scanf("%d %d %d", &v, &d, &x); que[v].pb({d, x}); } dfs(1, 1, 1); for (int i = 1; i <= n; i++) printf("%lld%c", ans[i], " \n"[i==n]); return 0; }