模板
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db(x) cout<<"["<<#x<<"]="<<x<<endl
const ll maxn=1e6+10;
ll N,M;
ll seg[maxn],lazy[maxn];
ll a[maxn],b[maxn];
ll dep[maxn],sz[maxn],son[maxn],fa[maxn];//for dfs1
ll top[maxn],idx[maxn];// for dfs2
vector<ll> G[maxn];
ll tot;//用于重编号
ll dfs1(ll now,ll fath,ll depth){
dep[now] =depth;
sz[now] = 1;
fa[now] = fath;
ll maxson = -1;
for(ll i=0;i<G[now].size();i++){
ll v = G[now][i];
if(v==fath) continue; //continue 写法不易出错
sz[now]+=dfs1(v,now,depth+1);
if(sz[v]>maxson){maxson = sz[v];son[now] = v;}
}
return sz[now];
}
void dfs2(ll now,ll topf){
idx[now] = (++tot);
b[tot] = a[now];//
top[now] = topf;
if(!son[now])return ;
dfs2(son[now],topf);
for(ll i=0;i<G[now].size();i++){
ll v = G[now][i];
if(!idx[v]) dfs2(v,v);
}
}
void build(ll root,ll l,ll r){
if(l==r){
seg[root] = b[l];
return ;
}
ll mid = (l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
seg[root] = seg[root<<1]+seg[root<<1|1];
}
void push_down(ll root,ll l,ll r){
if(lazy[root]){
ll mid = (l+r)>>1;
seg[root<<1] += (mid-l+1)*lazy[root];
seg[root<<1|1]+=(r-mid)*lazy[root];
lazy[root<<1] +=lazy[root];
lazy[root<<1|1]+=lazy[root];
lazy[root]=0;
}
}
void pointAdd(ll root,ll l,ll r,ll pos,ll val){
if(l==r){
seg[root]+=val; return ;
}
push_down(root,l,r);
ll mid = (l+r)>>1;
if(pos<=mid) pointAdd(root<<1,l,mid,pos,val);
else pointAdd(root<<1|1,mid+1,r,pos,val);
seg[root] = seg[root<<1]+seg[root<<1|1];
}
void intervalAdd(ll root,ll l,ll r,ll x,ll y,ll val){
if(x<=l&&r<=y){
seg[root]+=val*(r-l+1);
lazy[root]+=val;
return ;
}
push_down(root,l,r);
ll mid = (l+r)>>1;
if(x<=mid) intervalAdd(root<<1,l,mid,x,y,val);
if(y>mid) intervalAdd(root<<1|1,mid+1,r,x,y,val);
seg[root] = seg[root<<1]+seg[root<<1|1];
}
ll intervalAsk(ll root,ll l, ll r,ll x,ll y){
if(x<=l&&r<=y){
return seg[root];
}
push_down(root,l,r);
ll mid = (l+r)>>1;
ll ans = 0;
if(x<=mid) ans+=intervalAsk(root<<1,l,mid,x,y);
if(y>mid) ans+=intervalAsk(root<<1|1,mid+1,r,x,y);
return ans;
}
ll treeSum(ll x,ll y){
ll ans = 0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ll t=intervalAsk(1,1,N,idx[top[x]],idx[x]);
ans+=t;
x = fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans+=intervalAsk(1,1,N,idx[x],idx[y]);
return ans;
}
int main(){
scanf("%lld %lld",&N,&M);
for(ll i=1;i<=N;i++)scanf("%lld",a+i);
for(ll i=1;i<N;i++){
ll u,v;
scanf("%lld %lld",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs1(1,0,1);dfs2(1,1);
build(1,1,N);
while(M--){
ll op,x,val;
scanf("%lld",&op);
if(op==1){
scanf("%lld %lld",&x,&val);
pointAdd(1,1,N,idx[x],val);
}
else if(op==2){
scanf("%lld %lld",&x,&val);
intervalAdd(1,1,N,idx[x],idx[x]+sz[x]-1,val);
}
else{
scanf("%lld",&x);
printf("%lld
",treeSum(1,x));
}
}
}