題目連接:http://codeforces.com/contest/1076/problem/E
本題大意:
給一棵根節點為“1”樹,給m個操作,每個操作三個整數,v,d,x,意思是從節點1,往下深度d,遍及的節點的值都加上x,d可能是0,就是只加在自己上。結束m個操作后輸出每個節點的值。
解題思路:
這裡不應該考慮同時操作整棵樹。因為每個節點的子樹是多樣的,而應該以dfs的形式,直接搜到葉子節點,這樣沿途就是一條鏈。每時每刻都在操作一條鏈,也就是一段區間。這樣操作轉化為:一個節點往後的距離為d的區間內都加上x,這樣問題就轉變成了區間修改的問題,利用樹狀數組來實現。
存在疑問的地方應該是,當搜不同的葉子節點的時候,鏈是不一樣的,如何鏈的變化。只要想一下,從一個葉子到另一個葉子,不就是區間修改——把前一個葉子的影響去掉,然後加上另一個葉子的影響不就好了嗎?也就是說,dfs回退是把回退掉的點的影響去掉,這在樹狀數組上實現就是回退時加上一個-x就好了。
下面是AC代碼:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=3e5+7; 5 struct Node 6 { 7 int v,next; 8 }a[N<<1]; 9 struct Flag//記錄操作 10 { 11 int d,x; 12 }; 13 int n,cnt; 14 15 int head[N];//前向星 16 inline void add(int u,int v) 17 { 18 a[cnt].v=v; 19 a[cnt].next=head[u]; 20 head[u]=cnt++; 21 } 22 23 ll tr[N],ans[N];//樹狀數組,答案 24 inline void update(int x,int v) 25 { 26 for(;x<N;x+=x&-x) 27 tr[x]+=v; 28 } 29 30 inline ll sum(int x) 31 { 32 ll ret=0; 33 for(;x>0;x-=x&-x) 34 ret+=tr[x]; 35 return ret; 36 } 37 38 vector<Flag> v[N];//存儲每個節點的操作 39 bool vis[N]; 40 void dfs(int now,int dep) 41 { 42 vis[now]=1; 43 int nd,nx; 44 45 for(int i=0;i<v[now].size();++i)//讓當前節點的操作生效 46 { 47 nd=min(dep+v[now][i].d,n); 48 nx=v[now][i].x; 49 update(dep,nx); 50 update(nd+1,-nx); 51 } 52 53 ans[now]=sum(dep);//記錄當前節點的值 54 55 for(int i=head[now];i!=-1;i=a[i].next)//繼續往下 56 { 57 if(vis[a[i].v]) 58 continue; 59 dfs(a[i].v,dep+1); 60 } 61 62 for(int i=0;i<v[now].size();++i)//回退時把在該節點生效的操作撤銷 63 { 64 nd=min(dep+v[now][i].d,n); 65 nx=v[now][i].x; 66 update(dep,-nx);//樹狀數組上加上負數 67 update(nd+1,nx); 68 } 69 } 70 int main() 71 { 72 int x,y; 73 memset(head,-1,sizeof(head)); 74 scanf("%d",&n); 75 for(int i=1;i<n;++i) 76 { 77 scanf("%d%d",&x,&y); 78 add(x,y); 79 add(y,x); 80 } 81 int q; 82 scanf("%d",&q); 83 int t; 84 Flag temp; 85 for(int i=1;i<=q;++i) 86 { 87 scanf("%d%d%d",&t,&temp.d,&temp.x);//把操作裝到各點的vector里 88 v[t].push_back(temp); 89 } 90 dfs(1,1); 91 for(int i=1;i<n;++i) 92 printf("%lld ",ans[i]); 93 printf("%lld\n",ans[n]); 94 }
原文地址:https://www.cnblogs.com/Lin88/p/9973575.html
时间: 2024-10-16 15:52:51