#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define x_lc ((x<<1))
#define x_rc ((x<<1)|1)
#define x_mid ((t[x].l+t[x].r)>>1)
#define inf (1LL<<62)
#define SIZE 100001
struct node{
ll l,r;
ll vl,vr;
ll data;
ll sum;
ll tag;
void update(ll x){
tag=x;
sum=(r-l+1)*x;
vl=max(sum,0LL);
vr=max(sum,0LL);
data=max(sum,0LL);
}
};
node operator+(node x,node y){
node res;
res.l=x.l;
res.r=y.r;
res.tag=inf;
res.sum=x.sum+y.sum;
res.data=max(x.data,y.data);
res.data=max(res.data,x.vr+y.vl);
res.vl=max(x.vl,x.sum+y.vl);
res.vr=max(y.vr,y.sum+x.vr);
return res;
}
struct tree{
node t[SIZE];
void build(ll x,ll l,ll r){
t[x].l=l;
t[x].r=r;
t[x].tag=inf;
if(l==r) return;
build(x_lc,l,x_mid);
build(x_rc,x_mid+1,r);
}
void push_down(ll x){
if(t[x].tag!=inf){
t[x_lc].update(t[x].tag);
t[x_rc].update(t[x].tag);
t[x].tag=inf;
}
}
void change(ll x,ll l,ll r,ll y){
if(t[x].l>=l&&t[x].r<=r){
t[x].update(y);
return;
}
push_down(x);
if(x_mid>=l) change(x_lc,l,r,y);
if(x_mid+1<=r) change(x_rc,l,r,y);
t[x]=t[x_lc]+t[x_rc];
}
node query(ll x,ll l,ll r){
if(t[x].l>=l&&t[x].r<=r) return t[x];
push_down(x);
if(x_mid>=l&&x_mid+1<=r) return query(x_lc,l,r)+query(x_rc,l,r);
if(x_mid>=l) return query(x_lc,l,r);
return query(x_rc,l,r);
}
void print(ll x){
if(t[x].l==t[x].r){
cout<<t[x].sum<<" ";
return;
}
push_down(x);
print(x_lc);
print(x_rc);
}
}SGT;
ll n,q,cnt;
ll w[SIZE];
ll fa[SIZE],d[SIZE];
ll sz[SIZE],son[SIZE];
ll id[SIZE],top[SIZE];
vector<ll> r[SIZE];
void dfs1(ll x){
sz[x]=1;
for(ll i=0;i<r[x].size();i++){
ll y=r[x][i];
if(y==fa[x]) continue;
fa[y]=x;
d[y]=d[x]+1;
dfs1(y);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]])
son[x]=y;
}
}
void dfs2(ll x,ll t){
id[x]=++cnt;
top[x]=t;
SGT.change(1,id[x],id[x],w[x]);
if(son[x]==0) return;
dfs2(son[x],t);
for(ll i=0;i<r[x].size();i++){
ll y=r[x][i];
if(y==fa[x]) continue;
if(y==son[x]) continue;
dfs2(y,y);
}
}
void change(ll x,ll y,ll k){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
SGT.change(1,id[top[x]],id[x],k);
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
SGT.change(1,id[x],id[y],k);
}
ll query(ll x,ll y){
node left,right,tot;
left.data=-1;
right.data=-1;
while(top[x]!=top[y]){
if(d[top[x]]>d[top[y]]){
if(left.data==-1) left=SGT.query(1,id[top[x]],id[x]);
else left=left+SGT.query(1,id[top[x]],id[x]);
x=fa[top[x]];
}
else{
if(right.data==-1) right=SGT.query(1,id[top[y]],id[y]);
else right=SGT.query(1,id[top[y]],id[y])+right;
y=fa[top[y]];
}
}
if(d[x]<=d[y]) tot=SGT.query(1,id[x],id[y]);
else tot=SGT.query(1,id[y],id[x]),swap(tot.vl,tot.vr);
if(left.data!=-1) tot=left+tot;
if(right.data!=-1) tot=tot+right;
return tot.data;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
SGT.build(1,1,n);
for(ll i=1;i<=n;i++) cin>>w[i];
for(ll i=1;i<n;i++){
ll x,y;
cin>>x>>y;
r[x].push_back(y);
r[y].push_back(x);
}
dfs1(1);
dfs2(1,1);
cin>>q;
while(q--){
ll op,x,y;
cin>>op>>x>>y;
if(op==1)cout<<query(x,y)<<endl;
if(op==2){ll z;cin>>z;change(x,y,z);}
}
return 0;
}