#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 0x3f3f3f3f
#define xiaogendui priority_queue<int,vector<int>,greater<int> >
#define dagendui priority_queue<int,vector<int>,less<int> >
using namespace std;
double dmax(double a,double b){return a>b?a:b;}
double dmin(double a,double b){return a<b?a:b;}
int gcd(int a,int b){if(a<b)swap(a,b);if(a%b==0) return b;return gcd(b,a%b);}
ll ksm(ll a,ll b,ll p){ll s=1;a=a-a/p*p;while(b){if(b&1){s*=a;s=s-s/p*p;}a=a*a;a=a-a/p*p;b>>=1;}s=s-s/p*p;return s;}
int n,m;
const int qwqq=100010;
const int awaa=200010;
int w[qwqq],h[qwqq],e[awaa],ne[awaa],idx;
int id[qwqq],nw[qwqq],cnt;
int dep[qwqq],sz[qwqq],top[qwqq],fa[qwqq],son[qwqq];
struct node
{
int l;
int r;
ll add;
ll sum;
}tr[400010];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx;
idx++;
}
void dfs1(int u,int father,int depth)
{
dep[u]=depth;
fa[u]=father;
sz[u]=1;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(j==father) 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]=w[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]) continue;
dfs2(j,j);
}
}
void pushup(int u)
{
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void pushdown(int u)
{
auto &root=tr[u],&left=tr[u<<1],&right=tr[u<<1|1];
if(root.add)
{
left.add+=root.add;
left.sum+=root.add*(left.r-left.l+1);
right.add+=root.add;
right.sum+=root.add*(right.r-right.l+1);
root.add=0;
}
}
void build(int u,int l,int r)
{
tr[u]={l,r,0,nw[r]};
if(l==r) 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(l<=tr[u].l&&r>=tr[u].r)
{
tr[u].add+=k;
tr[u].sum+=k*(tr[u].r-tr[u].l+1);
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);
}
ll query(int u,int l,int r)
{
if(l<=tr[u].l&&r>=tr[u].r) return tr[u].sum;
pushdown(u);
ll res=0;
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) res+=query(u<<1,l,r);
if(r>mid) res+=query(u<<1|1,l,r);
return res;
}
void update_tree(int u,int k)
{
modify(1,id[u],id[u]+sz[u]-1,k);
}
ll query_tree(int u)
{
return query(1,id[u],id[u]+sz[u]-1);
}
void update_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);
}
ll query_path(int u,int v)
{
ll 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;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
memset(h,-1,sizeof(h));
for(int i=0;i<n-1;i++)
{
int qwq,awa;
scanf("%d%d",&qwq,&awa);
add(qwq,awa);
add(awa,qwq);
}
dfs1(1,-1,1);
dfs2(1,1);
build(1,1,n);
cin>>m;
for(int i=1;i<=m;i++)
{
int t,u,v,k;
scanf("%d%d",&t,&u);
if(t==1)
{
scanf("%d%d",&v,&k);
update_path(u,v,k);
}
else if(t==2)
{
scanf("%d",&k);
update_tree(u,k);
}
else if(t==3)
{
scanf("%d",&v);
printf("%lld\n",query_path(u,v));
}
else printf("%lld\n",query_tree(u));
}
}
一定要写pushdown!