#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int seg[MAXN],fa[MAXN],depth[MAXN];
int son[MAXN],siz[MAXN],top[MAXN],a[MAXN];
int nowval[MAXN];
int sumdfs;
int n,m;
struct node
{
int l,r,sum,num,lsum,rsum,Tar;
node(){ sum=num=lsum=rsum=Tar=0; }
}tree[MAXN<<2];
int head[MAXN],nxt[MAXN<<1],to[MAXN<<1],tot;
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void dfs1(int now,int pre)
{
fa[now]=pre,depth[now]=depth[pre]+1,siz[now]=1;
for(int i=head[now];i;i=nxt[i])
{
if(to[i]==pre) continue;
dfs1(to[i],now);
siz[now]+=siz[to[i]];
if(siz[to[i]]>siz[son[now]]) son[now]=to[i];
}
}
void dfs2(int x,int t)
{
seg[x]=++sumdfs,top[x]=t;
nowval[sumdfs]=a[x];
if(!son[x]) return;
if(son[x]) dfs2(son[x],t);
for(int i=head[x];i;i=nxt[i])
{
if(to[i]==fa[x]||to[i]==son[x]) continue;
dfs2(to[i],to[i]);
}
}
void pushup(int now)
{
tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
tree[now].lsum=max(tree[now<<1].lsum,tree[now<<1].sum+tree[now<<1|1].lsum);
tree[now].rsum=max(tree[now<<1|1].rsum,tree[now<<1|1].sum+tree[now<<1].rsum);
tree[now].num=max(tree[now<<1].rsum+tree[now<<1|1].lsum,max(tree[now<<1].num,tree[now<<1|1].num));
}
void build_tree(int now,int l,int r)
{
tree[now].l=l,tree[now].r=r,tree[now].Tar=-1e5;
if(l==r)
{
tree[now].lsum=tree[now].rsum=tree[now].num=tree[now].sum=nowval[l];
return;
}
int mid=(l+r)/2;
build_tree(now<<1,l,mid);
build_tree(now<<1|1,mid+1,r);
pushup(now);
}
void fixed_tree(int now)
{
if(tree[now].Tar!=-1e5)
{
tree[now<<1].Tar=tree[now<<1|1].Tar=tree[now].Tar;
tree[now<<1].sum=(tree[now<<1].r-tree[now<<1].l+1)*tree[now].Tar;
tree[now<<1|1].sum=(tree[now<<1|1].r-tree[now<<1|1].l+1)*tree[now].Tar;
if(tree[now].Tar<0) tree[now<<1].lsum=tree[now<<1].num=tree[now<<1].rsum=tree[now].Tar;
else tree[now<<1].lsum=tree[now<<1].num=tree[now<<1].rsum=tree[now<<1].sum;
if(tree[now].Tar<0) tree[now<<1|1].lsum=tree[now<<1|1].num=tree[now<<1|1].rsum=tree[now].Tar;
else tree[now<<1|1].lsum=tree[now<<1|1].num=tree[now<<1|1].rsum=tree[now<<1|1].sum;
tree[now].Tar=-1e5;
}
}
node merge(node x,node y)
{
node res;
res.sum=x.sum+y.sum,res.num=max(x.rsum+y.lsum,max(x.num,y.num));
res.lsum=max(x.lsum,x.sum+y.lsum),res.rsum=max(y.rsum,y.sum+x.rsum);
return res;
}
void change_tree(int now,int l,int r,int v)
{
if(l<=tree[now].l&&tree[now].r<=r)
{
tree[now].sum=(tree[now].r-tree[now].l+1)*v;
if(v<0) tree[now].lsum=tree[now].num=tree[now].rsum=v;
else tree[now].lsum=tree[now].num=tree[now].rsum=tree[now].sum;
tree[now].Tar=v;
return;
}
fixed_tree(now);
int mid=(tree[now].l+tree[now].r)/2;
if(l<=mid) change_tree(now<<1,l,r,v);
if(r>mid) change_tree(now<<1|1,l,r,v);
pushup(now);
}
node query(int now,int l,int r)
{
node f1,f2;
if(l<=tree[now].l&&tree[now].r<=r) return tree[now];
fixed_tree(now);
int mid=(tree[now].l+tree[now].r)/2;
if(l<=mid) f1=query(now<<1,l,r);
if(r>mid) f2=query(now<<1|1,l,r);
return merge(f1,f2);
}
void changeway(int l,int r,int v)
{
while(top[l]!=top[r])
{
if(depth[top[l]]<depth[top[r]]) swap(l,r);
change_tree(1,seg[top[l]],seg[l],v);
l=fa[top[l]];
}
if(depth[l]>depth[r]) swap(l,r);
change_tree(1,seg[l],seg[r],v);
}
node queryway(int l,int r)
{
node L,R;
while(top[l]!=top[r])
{
if(depth[top[l]]<depth[top[r]])
{
R=merge(R,query(1,seg[top[r]],seg[r]));
r=fa[top[r]];
}
else
{
L=merge(L,query(1,seg[top[l]],seg[l]));
l=fa[top[l]];
}
}
if(depth[l]>depth[r]) L=merge(L,query(1,seg[r],seg[l]));
else R=merge(R,query(1,seg[l],seg[r]));
swap(L.lsum,L.rsum);
return merge(L,R);
}
void read(int &x)
{
x=0;
short flag=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
x*=flag;
}
int main()
{
read(n);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<n;i++)
{
int x,y;
read(x),read(y);
add(x,y),add(y,x);
}
dfs1(1,0),dfs2(1,1);
build_tree(1,1,n);
read(m);
while(m--)
{
int opt,x,y,z;
read(opt),read(x),read(y);
if(opt==1) cout<<max(queryway(x,y).num,0)<<endl;
else read(z),changeway(x,y,z);
}
return 0;
}