CF1076E Vasya and a Tree
如果只是把
大概思路是维护一些vector,第 vector按照dfs序的 vector中,且 vector中对应的区间,那么把 k-son 加
那如果把 0-son,1-son...k-son 全部加呢?只需要再差分一遍(树上差分)就行了。最后问题变为把
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define int long long
int c[300005], In[300005], Out[300005], idx[300005], n, cnt;
int s[300005], dep[300005], p[300005];
std::vector<int> G[300005], vec[300005], vec2[300005];
void update(int l, int r, int d) {
for (int i = l; i <= n; i += (i & ~i + 1)) c[i] += d;
for (int i = r + 1; i <= n; i += (i & ~i + 1)) c[i] -= d;
}
int query(int x) {
int sum = 0;
for (int i = x; i; i -= (i & ~i + 1)) sum += c[i];
return sum;
}
void dfs(int u, int fa) {
vec[dep[u] = dep[fa] + 1].push_back(In[u] = ++ cnt);
vec2[dep[u]].push_back(u);
for (int v : G[u]) if (v != fa) dfs(v, u);
Out[u] = cnt;
}
void DFS(int u, int fa) {
s[u] += query(p[u]);
for (int v : G[u])
if (v != fa) s[v] += s[u], DFS(v, u);
}
signed main() {
scanf("%lld", &n);
for (int i = 1; i < n; ++ i) {
int u, v;
scanf("%lld%lld", &u, &v);
G[u].push_back(v), G[v].push_back(u);
}
dfs(1, -1);
idx[0] = 1;
for (int i = 1; vec[i].size(); ++ i) {
idx[i] = idx[i - 1] + vec[i - 1].size();
for (int j = 0; j < vec[i].size(); ++ j)
p[vec2[i][j]] = idx[i] + j;
}
int m;
scanf("%lld", &m);
for (int i = 1; i <= m; ++ i) {
int x, d, u, k;
scanf("%lld%lld%lld", &u, &d, &x);
s[u] += x, k = dep[u] + d + 1;
if (n < k || !vec[k].size()) continue;
int st = std::lower_bound(vec[k].begin(), vec[k].end(), In[u]) - vec[k].begin();
int ed = std::upper_bound(vec[k].begin(), vec[k].end(), Out[u]) - vec[k].begin() - 1;
update(idx[k] + st, idx[k] + ed, -x);
}
DFS(1, -1);
for (int i = 1; i <= n; ++ i) printf("%lld ", s[i]);
return 0;
}