#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5; #define mid ((l+r)>>1) #define left_son root<<1,l,mid #define right_son root<<1|1,mid+1,r #define ll long long int n,m; int e,begin[maxn],next[maxn],to[maxn],w[maxn]; struct segment_tree{ ll sum,mark,l,r; }tree[maxn<<2]; int son[maxn],id[maxn],father[maxn],cnt,deep[maxn],size[maxn],top[maxn],_map[maxn]; inline void add(int x,int y){ to[++e] = y; next[e] = begin[x]; begin[x] = e; } inline void pushup(int root){ tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum; } inline void pushdown(int root){ if(tree[root].mark){ tree[root<<1].mark += tree[root].mark; tree[root<<1|1].mark += tree[root].mark; tree[root<<1].sum += tree[root].mark*(tree[root<<1].r-tree[root<<1].l+1); tree[root<<1|1].sum += tree[root].mark*(tree[root<<1|1].r-tree[root<<1|1].l+1); tree[root].mark = 0; } } inline void build(int root,int l,int r){ tree[root].l = l; tree[root].r = r; tree[root].mark = 0; if(l == r){ tree[root].sum = w[_map[l]]; return; } build(left_son); build(right_son); pushup(root); } inline void update(int root,int l,int r,int al,int ar,ll k){ if(al > r || ar < l)return; if(al <= l && ar >= r){ tree[root].mark += k; tree[root].sum += k*(r-l+1); return; } pushdown(root); update(left_son,al,ar,k); update(right_son,al,ar,k); pushup(root); } inline ll query(int root,int l,int r,int al,int ar){ if(al > r || ar < l)return 0; if(al <= l && ar >= r)return tree[root].sum; pushdown(root); return query(left_son,al,ar)+query(right_son,al,ar); } inline ll query_range(int x,int y){ ll ans = 0; while(top[x] != top[y]){ if(deep[top[x]] < deep[top[y]])swap(x,y); ans += query(1,1,cnt,id[top[x]],id[x]); x = father[top[x]]; } if(deep[x] > deep[y])swap(x,y); ans += query(1,1,cnt,id[x],id[y]); return ans; } inline void dfs1(int x,int fa,int dep){ deep[x] = dep; father[x] = fa; size[x] = 1; int maxson = -1; for(int i = begin[x];i;i = next[i]){ int y = to[i]; if(y == fa)continue; dfs1(y,x,dep+1); size[x] += size[y]; if(size[y] > maxson)son[x] = y,maxson = size[y]; } } inline void dfs2(int x,int ntop){ id[x] = ++cnt; top[x] = ntop; _map[id[x]] = x; if(!son[x])return; dfs2(son[x],ntop); for(int i = begin[x];i;i = next[i]){ int y = to[i]; if(y == father[x] || y == son[x])continue; dfs2(y,y); } } int main(){ cin>>n>>m; for(int i = 1;i <= n;i++)scanf("%d",&w[i]); for(int i = 1,u,v;i < n;i++){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs1(1,0,1); dfs2(1,1); build(1,1,cnt); while(m--){ ll x,y,dispose; scanf("%lld%lld",&dispose,&x); if(dispose == 1){ scanf("%lld",&y); update(1,1,cnt,id[x],id[x],y); } if(dispose == 2){ scanf("%lld",&y); update(1,1,cnt,id[x],id[x]+size[x]-1,y); } if(dispose == 3)printf("%lld ",query_range(1,x)); } return 0; }