1. 程式人生 > >Vasya and a Tree [contest/1076 E]

Vasya and a Tree [contest/1076 E]

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]); }