#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+1;
int n,q;
int w[N];
vector<int>e[N];
int dep[N],fa[N],hson[N],sz[N];
int dfn[N],val[N],top[N],cnt;
inline void dfs1(int u)
{
dep[u]=dep[fa[u]]+1;
sz[u]=1,hson[u]=-1;
for(int v:e[u])
{
if(!dep[v])
{
fa[v]=u;
dfs1(v);
sz[u]+=sz[v];
if(hson[u]==-1||sz[v]>sz[hson[u]])
hson[u]=v;
}
}
}
inline void dfs2(int u,int Top)
{
top[u]=Top;
dfn[u]=++cnt;
val[cnt]=u;
if(hson[u]==-1)return;
dfs2(hson[u],Top);
for(int v:e[u])
{
if(v!=fa[u]&&v!=hson[u])
dfs2(v,v);
}
}
namespace SGT{
struct Seg{
int maxl,maxr,Max,sum,tag;bool flag;
Seg(){maxl=maxr=Max=sum=tag=flag=0;}
}seg[N<<2];
#define mid ((l+r)>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
inline Seg merge(Seg L,Seg R)
{
Seg res;
res.sum=L.sum+R.sum;
res.maxl=max(L.maxl,L.sum+R.maxl);
res.maxr=max(R.maxr,R.sum+L.maxr);
res.Max=max({L.Max,R.Max,L.maxr+R.maxl});
res.flag=res.tag=0;
return res;
}
inline void build(int rt,int l,int r)
{
if(l==r)
{
seg[rt].Max=seg[rt].maxl=seg[rt].maxr=max(0ll,w[val[l]]);
seg[rt].sum=w[val[l]];
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
seg[rt]=merge(seg[ls],seg[rs]);
}
inline void push_down(int rt,int l,int r)
{
if(seg[rt].flag)
{
int x=seg[rt].tag;
seg[ls].Max=seg[ls].maxl=seg[ls].maxr=max(0ll,x*(mid-l+1));
seg[ls].sum=x*(mid-l+1);seg[ls].flag=1,seg[ls].tag=x;
seg[rs].Max=seg[rs].maxl=seg[rs].maxr=max(0ll,x*(r-mid+2));
seg[rs].sum=x*(r-mid+2);seg[rs].flag=1,seg[rs].tag=x;
seg[rt].flag=seg[rt].tag=0;
}
}
inline void Modify(int rt,int l,int r,int L,int R,int x)
{
if(L>r||R<l)return;
if(L<=l&&r<=R)
{
seg[rt].Max=seg[rt].maxl=seg[rt].maxr=max(x*(r-l+1),0ll);
seg[rt].sum=x*(r-l+1);seg[rt].flag=1,seg[rt].tag=x;
return;
}
push_down(rt,l,r);
Modify(ls,l,mid,L,R,x);
Modify(rs,mid+1,r,L,R,x);
seg[rt]=merge(seg[ls],seg[rs]);
}
inline Seg Query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return seg[rt];
}
push_down(rt,l,r);
Seg Ls,Rs;
if(L<=mid)Ls=Query(ls,l,mid,L,R);
if(R>mid)Rs=Query(rs,mid+1,r,L,R);
return merge(Ls,Rs);
}
}using namespace SGT;
inline void Rvs(int x,int y,int v)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<=dep[fy])
swap(x,y),swap(fx,fy);
Modify(1,1,n,dfn[fx],dfn[x],v);
x=fa[fx],fx=top[x];
}
if(dfn[x]>dfn[y])
swap(x,y);
Modify(1,1,n,dfn[x],dfn[y],v);
}
inline Seg QSum(int x,int y)
{
Seg L,R;
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]>=dep[fy])
L=merge(Query(1,1,n,dfn[fx],dfn[x]),L),x=fa[fx],fx=top[x];
else R=merge(Query(1,1,n,dfn[fy],dfn[y]),R),y=fa[fy],fy=top[y];
}
if(dfn[x]>dep[y])
L=merge(Query(1,1,n,dfn[y],dfn[x]),L);
else R=merge(Query(1,1,n,dfn[x],dfn[y]),R);
swap(L.maxl,L.maxr);
return merge(L,R);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>w[i];
for(int i=1;i<n;i++)
{
int u,v;cin>>u>>v;
e[u].emplace_back(v);
e[v].emplace_back(u);
}
dfs1(1);
dfs2(1,1);
build(1,1,n);
cin>>q;
while(q--)
{
int opt,a,b,c;
cin>>opt>>a>>b;
if(opt==1)
{
cout<<QSum(a,b).Max<<'\n';
}
else
{
cin>>c;
Rvs(a,b,c);
}
}
return 0;
}