版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z591826160/article/details/84027280
Vasya and a Tree [contest/1076 E]
题面
思路
看到修改一个子树内容,第一反应是打标记,但由于只修改深度范围内的节点,容易想到用类似差分的思想去做。说到差分那首选就是树状数组了,维护每个节点的修改情况,进入节点时,将拆分内容加入线段树,出该节点时恢复差分情况即可
代码
int n,m;
vector<int>G[maxn];
vector<pair<int,int> >update[maxn];
int dep[maxn];
ll tree[maxn],ans[maxn];
void add(int u,ll c){
while(u<=n){
tree[u]+=c;
u+=lowbit(u);
}
}
ll query(int u){
ll ans=0;
while(u){
ans+=tree[u];
u-=lowbit(u);
}
return ans;
}
void dfs(int u,int f,int d){
dep[u]=d;
rep(i,0,update[u].size()){
add(dep[u],update[u][i].second);
add(dep[u]+update[u][i].first+1,-update[u][i].second);
}
ans[u]=query(dep[u]);
rep(i,0,G[u].size()){
int v=G[u][i];
if(v==f)continue;
dfs(v,u,d+1);
}
rep(i,0,update[u].size()){
add(dep[u],-update[u][i].second);
add(dep[u]+update[u][i].first+1,update[u][i].second);
}
}
int main(){
rd(n);
rep(i,1,n){
int a,b;
rd(a,b);
G[a].pb(b);G[b].pb(a);
}
rd(m);
rep(i,0,m){
int a,b,c;
rd(a,b,c);
update[a].pb(mp(b,c));
}
dfs(1,-1,1);
rep(i,1,n+1)
printf("%lld ",ans[i]);
}