Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
Input
第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Sample Input
5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
Sample Output
6
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 using namespace std; 6 const int maxn=100010; 7 int cnt,fir[maxn],to[maxn<<1],nxt[maxn<<1],n,m; 8 void addedge(int a,int b){ 9 nxt[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt; 10 } 11 long long key[maxn],tr[maxn<<2],add[maxn<<2]; 12 int ID[maxn],fa[maxn],top[maxn],end[maxn],sz[maxn],son[maxn]; 13 void Push_up(int x){ 14 tr[x]=tr[x<<1]+tr[x<<1|1]; 15 } 16 void Add(int x,int l,int r,long long d){ 17 tr[x]+=(r-l+1)*d; 18 add[x]+=d; 19 } 20 void Push_down(int x,int l,int r){ 21 if(add[x]){ 22 int mid=(l+r)>>1; 23 Add(x<<1,l,mid,add[x]); 24 Add(x<<1|1,mid+1,r,add[x]); 25 add[x]=0; 26 } 27 } 28 void Updata(int node,int l,int r,int a,int b,long long d){ 29 if(l>=a&&r<=b){ 30 Add(node,l,r,d); 31 return; 32 } 33 Push_down(node,l,r); 34 int mid=(l+r)>>1; 35 if(mid>=a)Updata(node<<1,l,mid,a,b,d); 36 if(mid<b) Updata(node<<1|1,mid+1,r,a,b,d); 37 Push_up(node); 38 } 39 long long Query(int node,int l,int r,int a,int b){ 40 if(l>=a&&r<=b)return tr[node]; 41 Push_down(node,l,r); 42 int mid=(l+r)>>1; 43 long long ret=0; 44 if(mid>=a)ret=Query(node<<1,l,mid,a,b); 45 if(mid<b) ret+=Query(node<<1|1,mid+1,r,a,b); 46 return ret; 47 } 48 void DFS(int x){ 49 sz[x]=1; 50 for(int i=fir[x];i;i=nxt[i]){ 51 if(to[i]==fa[x])continue; 52 fa[to[i]]=x; 53 DFS(to[i]); 54 sz[x]+=sz[to[i]]; 55 son[x]=sz[son[x]]<sz[to[i]]?to[i]:son[x]; 56 } 57 } 58 long long Solve(int y){ 59 long long ret=0; 60 while(y){ 61 ret+=Query(1,1,n,ID[top[y]],ID[y]); 62 y=fa[top[y]]; 63 } 64 return ret; 65 } 66 int cont; 67 void DFS2(int x,int tp){ 68 ID[x]=++cont;top[x]=tp; 69 if(son[x])DFS2(son[x],tp); 70 for(int i=fir[x];i;i=nxt[i]) 71 if(to[i]!=fa[x]&&to[i]!=son[x]) 72 DFS2(to[i],to[i]); 73 end[x]=cont; 74 } 75 int main(){ 76 freopen("t2.in","r",stdin); 77 freopen("t2.out","w",stdout); 78 scanf("%d %d",&n,&m); 79 for(int i=1;i<=n;i++) 80 scanf("%lld",&key[i]); 81 82 for(int i=1,a,b;i<n;i++){ 83 scanf("%d %d",&a,&b); 84 addedge(a,b); 85 addedge(b,a); 86 } 87 88 DFS(1); 89 DFS2(1,1); 90 91 for(int i=1;i<=n;i++) 92 Updata(1,1,n,ID[i],ID[i],key[i]); 93 int op,x,a; 94 while(m--){ 95 scanf("%d",&op); 96 if(op==1){ 97 scanf("%d%d",&x,&a); 98 Updata(1,1,n,ID[x],ID[x],a); 99 } 100 else if(op==2){ 101 scanf("%d%d",&x,&a); 102 Updata(1,1,n,ID[x],end[x],a); 103 } 104 else{ 105 scanf("%d",&x); 106 printf("%lld\n",Solve(x)); 107 } 108 } 109 return 0; 110 }
时间: 2024-10-07 17:01:46