#include <bits/stdc++.h> using namespace std; #define x first #define y second # define rep(i,be,en) for(int i=be;i<=en;i++) # define pre(i,be,en) for(int i=be;i>=en;i--) #define ll long long #define endl "\n" #define LOCAL #define pb push_back #define int long long typedef pair<ll, ll> PII; #define eb emplace_back #define sp(i) setprecision(i) const int N = 2e5 + 10, INF = 0x3f3f3f3f; int h[N],ne[N],e[N],idx; int n,m; int a[N]; int dep[N],fa[N],top[N]; int sz[N]; int son[N]; int id[N]; int nw[N]; int cnt; struct node { int l; int r; int tag; int sum; }tr[N<<2]; void add(int a,int b) { ne[idx]=h[a],e[idx]=b,h[a]=idx++; } void dfs1(int u,int f,int depth) { dep[u]=depth,fa[u]=f,sz[u]=1; for(int i=h[u];~i;i=ne[i]) { int j=e[i]; if(j==f) continue; dfs1(j,u,depth+1); sz[u]+=sz[j]; if(sz[son[u]]<sz[j]) son[u]=j; } } void dfs2(int u,int t) { id[u]=++cnt; nw[cnt]=a[u]; top[u]=t; if(!son[u]) return; dfs2(son[u],t); for(int i=h[u];~i;i=ne[i]) { int j=e[i]; if(j!=fa[u]&&j!=son[u]) dfs2(j,j); } } void pushup(int u) { tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum; } void pushdown(int u) { if(tr[u].tag) { tr[u<<1].tag+=tr[u].tag; tr[u<<1|1].tag+=tr[u].tag; tr[u<<1].sum+=tr[u].tag*(tr[u<<1].r-tr[u<<1].l+1); tr[u<<1|1].sum+=tr[u].tag*(tr[u<<1|1].r-tr[u<<1|1].l+1); tr[u].tag=0; } } void build(int u,int l,int r) { tr[u]={l,r}; if(l==r) { tr[u].sum=nw[l]; return; } int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); pushup(u); } void modify(int u,int l,int r,int k) { if(tr[u].l>=l&&tr[u].r<=r) { tr[u].sum+=k*(tr[u].r-tr[u].l+1); tr[u].tag+=k; return; } pushdown(u); int mid=tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,r,k); if(r>mid) modify(u<<1|1,l,r,k); pushup(u); } int query(int u,int l,int r) { if(tr[u].l>=l&&tr[u].r<=r) { return tr[u].sum; } pushdown(u); int mid=tr[u].l+tr[u].r>>1; int ans=0; if(l<=mid) ans+=query(u<<1,l,r); if(r>mid) ans+=query(u<<1|1,l,r); return ans; } void modify_tree(int u,int k) { modify(1,id[u],id[u]+sz[u]-1,k); } int query_tree(int u) { return query(1,id[u],id[u]+sz[u]-1); } void modify_path(int u,int v,int k) { while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]]) swap(u,v); modify(1,id[top[u]],id[u],k); u=fa[top[u]]; } if(dep[u]<dep[v]) swap(u,v); modify(1,id[v],id[u],k); } int query_path(int u,int v) { int res=0; while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]]) swap(u,v); res+=query(1,id[top[u]],id[u]); u=fa[top[u]]; } if(dep[u]<dep[v]) swap(u,v); res+=query(1,id[v],id[u]); return res; } void solve() { scanf("%lld",&n); memset(h,-1,sizeof(h)); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } for(int i=1;i<n;i++) { int a,b; scanf("%lld%lld",&a,&b); add(a,b); add(b,a); } dfs1(1,-1,1); dfs2(1,1);//当前点,当前点所在重链的顶点 build(1,1,n); scanf("%lld",&m); for(int i=1;i<=m;i++) { int op,u,v,k; scanf("%lld",&op); if(op==1) { scanf("%lld%lld%lld",&u,&v,&k); modify_path(u,v,k); }else if(op==2) { scanf("%lld%lld",&u,&k); modify_tree(u,k); }else if(op==3) { scanf("%lld%lld",&u,&v); cout<<query_path(u,v)<<endl; }else{ scanf("%lld",&u); cout<<query_tree(u)<<endl; } } } signed main() { //#ifdef LOCAL //freopen("data.in.txt","r",stdin); //freopen("data.out.txt","w",stdout); //#endif int __ = 1; //cin>>__; while (__--) { solve(); } return 0; }