#include<bits/stdc++.h>
#define ll long long
#define inf 4557430888798830399
using namespace std;
const ll N=100010,M=N*2;
const ll NUM=1e18;
ll n,m;
ll a[N];
ll h[N],e[M],ne[M],idx;
ll d[N],sz[N],fa[N],son[N];
ll id[N],na[N],top[N],cnt;
struct nd{
ll l,r;
ll sum,tmax,lmax,rmax;
ll tag;
}tr[N*4];
void adds(ll a,ll b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs1(ll u,ll father,ll dep){
d[u]=dep,sz[u]=1,fa[u]=father;
for(ll i=h[u];~i;i=ne[i]){
ll v=e[i];
if(v==father) continue;
dfs1(v,u,dep+1);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(ll u,ll t){
id[u]=++cnt,na[cnt]=a[u],top[u]=t;
if(!son[u]) return;
dfs2(son[u],t);
for(ll i=h[u];~i;i=ne[i]){
ll v=e[i];
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
void merge(nd &root,nd &left,nd &right){
root.sum=left.sum+right.sum;
root.lmax=left.lmax;
if(left.tmax==left.sum) root.lmax=max(root.lmax,left.sum+right.lmax);
root.rmax=right.rmax;
if(right.tmax==right.sum) root.rmax=max(root.rmax,right.sum+left.rmax);
root.tmax=max(max(left.tmax,right.tmax),left.rmax+right.lmax);
}
void pushup(ll u){
merge(tr[u],tr[u<<1],tr[u<<1|1]);
}
void change_to(nd &t,ll k){
t.sum=k*(t.r-t.l+1);
t.lmax=t.rmax=t.tmax=max(k*(t.r-t.l+1),k);
t.tag=k;
}
void pushdown(ll u){
nd &root=tr[u],&left=tr[u<<1],&right=tr[u<<1|1];
if(root.tag!=NUM){
change_to(left,root.tag),change_to(right,root.tag);
root.tag=NUM;
}
}
void build(ll u,ll l,ll r){
tr[u]={l,r,na[r],na[r],na[r],na[r],NUM};
if(l==r) return;
ll mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void update(ll u,ll l,ll r,ll k){
if(l<=tr[u].l&&tr[u].r<=r){
change_to(tr[u],k);
return;
}
pushdown(u);
ll mid=tr[u].l+tr[u].r>>1;
if(l<=mid) update(u<<1,l,r,k);
if(r>mid) update(u<<1|1,l,r,k);
pushup(u);
}
nd query(ll u,ll l,ll r){
if(l<=tr[u].l&&tr[u].r<=r){
return tr[u];
}
pushdown(u);
ll mid=tr[u].l+tr[u].r>>1;
if(r<=mid) return query(u<<1,l,r);
if(l>mid) return query(u<<1|1,l,r);
nd root,left=query(u<<1,l,r),right=query(u<<1|1,l,r);
merge(root,left,right);
return root;
}
void update_path(ll u,ll v,ll k){
while(top[u]!=top[v]){
if(d[top[u]]<d[top[v]]) swap(u,v);
update(1,id[top[u]],id[u],k);
u=fa[top[u]];
}
if(d[u]<d[v]) swap(u,v);
update(1,id[v],id[u],k);
}
nd query_path(ll u,ll v){
bool vis1=0,vis2=0;
nd left,right;
while(top[u]!=top[v]){
if(d[top[u]]>d[top[v]]){
nd t=query(1,id[top[u]],id[u]);
nd tleft=left;
if(!vis1) left=t,vis1=1;
else merge(left,t,tleft);
u=fa[top[u]];
}else{
nd t=query(1,id[top[v]],id[v]);
nd tright=right;
if(!vis2) right=t,vis2=1;
else merge(right,t,tright);
v=fa[top[v]];
}
}
if(d[u]>d[v]){
nd t=query(1,id[v],id[u]);
nd tleft=left;
if(!vis1) left=t,vis1=1;
else merge(left,t,tleft);
}else{
nd t=query(1,id[u],id[v]);
nd tright=right;
if(!vis2) right=t,vis2=1;
else merge(right,t,tright);
}
if(!vis1) return right;
if(!vis2) return left;
swap(left.lmax,left.rmax);
nd root;
merge(root,left,right);
return root;
}
int main(){
memset(h,-1,sizeof h);
scanf("%lld",&n);
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(ll i=1;i<n;i++){
ll x,y;
scanf("%lld%lld",&x,&y);
adds(x,y),adds(y,x);
}
dfs1(1,-1,1);
dfs2(1,1);
build(1,1,n);
scanf("%lld",&m);
while(m--){
ll op,x,y,z;
scanf("%lld",&op);
if(op==1){
scanf("%lld%lld",&x,&y);
printf("%lld\n",max(0ll,query_path(x,y).tmax));
}else{
scanf("%lld%lld%lld",&x,&y,&z);
update_path(x,y,z);
}
}
return 0;
}