CF1076E
题意:给你一棵以1为根的树,每次把以x为根,深度不大于k的点的值全部加上v。最后求每个结点的值。
题解
- dfs从根开始遍历,那么遍历到每一个点,其深度是确定的。
- x根的深度为dep,深度不大于k的点都加上v,相当于c[dep] + v,c[dep+k+1]-v,差分处理。
- 最后x根处理完之后,还有c[dep]-v,c[dep+k+1] + v。因为要遍历其它根,都在同一层,排除这个根的影响。
代码
#include <bits/stdc++.h>
using namespace std;
#define sd second
#define ft first
typedef long long ll;
typedef pair<int,int>pii;
int const N = 300000 + 10;
int n,m;
ll c[N],ans[N];
vector<int>G[N];
vector<pii>p[N];
int lowbit(int x){return x&-x;}
void add(int i,int x){
while(i <= N){
c[i] += x;
i += lowbit(i);
}
}
ll query(int i){
ll sum = 0;
while(i){
sum += c[i];
i -= lowbit(i);
}
return sum;
}
void dfs(int u,int fa,int dep){
for(int i=0;i<p[u].size();i++){
add(dep,p[u][i].sd);
add(dep+p[u][i].ft+1,-p[u][i].sd);
}
ans[u] = query(dep);
for(int i=0;i<G[u].size();i++){
int v = G[u][i];
if(v == fa) continue;
dfs(v,u,dep+1);
}
for(int i=0;i<p[u].size();i++){
add(dep,-p[u][i].sd);
add(dep+p[u][i].ft+1,p[u][i].sd);
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
scanf("%d",&m);
for(int i=0;i<m;i++){
int u,dep,val;
scanf("%d%d%d",&u,&dep,&val);
p[u].push_back(pii(dep,val));
}
dfs(1,0,1);
for(int i=1;i<=n;i++)
printf("%lld ",ans[i]);
return 0;
}