操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
树剖板子
const int N=1e5+79;
int a[N],b[N];
int n,m;
struct graph{
int head[N],tot,next[N<<1],ver[N<<1];
inline void add(int a,int b){
ver[++tot]=b;
next[tot]=head[a];
head[a]=tot;
}
}G;
int top[N],dep[N],fa[N],son[N],siz[N],dfn[N],tim;
inline void dfs1(int x){
siz[x]=1;
dep[x]=dep[fa[x]]+1;
repg(x){
int y(G.ver[i]);
if(y==fa[x]) continue;
fa[y]=x;
dfs1(y);
siz[x]+=siz[y];
if(siz[son[x]]<siz[y]){
son[x]=y;
}
}
}
inline void dfs2(int x,int topf){
dfn[x]=++tim;
b[tim]=a[x];
top[x]=topf;
if(son[x]){
dfs2(son[x],topf);
}
repg(x){
int y(G.ver[i]);
if(y==son[x]||y==fa[x]) continue;
dfs2(y,y);
}
}
struct SegmentTree{
int lc[N<<2],rc[N<<2];
lxl sum[N<<2],tag[N<<2];
int cnt,rt;
inline void pushup(int p){
sum[p]=sum[lc[p]]+sum[rc[p]];
}
inline void pushdown(int &p,int L,int R){
if(!tag[p]) return ;
int mid(L+R>>1);
if(lc[p]){
sum[lc[p]]+=(mid-L+1)*tag[p];
tag[lc[p]]+=tag[p];
}
if(rc[p]){
sum[rc[p]]+=(R-mid)*tag[p];
tag[rc[p]]+=tag[p];
}
tag[p]=0;
}
inline void build(int &p,int L,int R){
if(!p) p=++cnt;
if(L==R){
sum[p]=b[L];
return ;
}
int mid(L+R>>1);
build(lc[p],L,mid);
build(rc[p],mid+1,R);
pushup(p);
}
inline void change(int &p,int L,int R,int ll,int rr,lxl val){
if(!p) p=++cnt;
if(ll<=L&&rr>=R){
sum[p]+=(R-L+1)*val;
tag[p]+=val;
return;
}
pushdown(p,L,R);
int mid(L+R>>1);
if(ll<=mid) change(lc[p],L,mid,ll,rr,val);
if(rr>mid) change(rc[p],mid+1,R,ll,rr,val);
pushup(p);
}inline lxl query(int &p,int L,int R,int ll,int rr){
if(!p) return 0;
if(ll<=L&&rr>=R){
return sum[p];
}
pushdown(p,L,R);
int mid(L+R>>1);
lxl ans(0);
if(ll<=mid) ans+=query(lc[p],L,mid,ll,rr);
if(rr>mid) ans+=query(rc[p],mid+1,R,ll,rr);
return ans;
}
}S;
inline lxl Qchain(int x,int y){
lxl ans(0);
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
ans+=S.query(S.rt,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y]) std::swap(x,y);
ans+=S.query(S.rt,1,n,dfn[x],dfn[y]);
return ans;
}
/*
5 1
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
*/
int main(){
read(n);read(m);
rep(i,1,n){
read(a[i]);
}
int a,y;
rep(i,2,n){
read(a);read(y);
G.add(a,y);
G.add(y,a);
}
dfs1(1);
dfs2(1,1);
S.build(S.rt,1,n);
int op,x;
rep(i,1,m){
read(op);
if(op==1){
read(x);read(a);
S.change(S.rt,1,n,dfn[x],dfn[x],a);
}else if(op==2){
read(x);read(a);
S.change(S.rt,1,n,dfn[x],dfn[x]+siz[x]-1,a);
}else {
read(x);
out(Qchain(1,x),'\n');
}
}
return 0;
}