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
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
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 }