#include <vector>
#include <stdio.h>
#define lc(id) (id<<1)
#define rc(id) (id<<1|1)
#define mid (l+r>>1)
using ll=long long;
const int maxn=100005;
int cnt;
std::vector<int> e[maxn];
int q[maxn];
int dep[maxn],fat[maxn],sz[maxn],dfn[maxn],son[maxn];
int top[maxn],rid[maxn];
inline void dfs1(int id,int fa)
{
dep[id]=dep[fa]+1;
fat[id]=fa;
sz[id]=1;
for(auto nxt:e[id])
{
if(nxt==fa)
continue;
dfs1(nxt,id);
sz[id]+=sz[nxt];
if(sz[nxt]>sz[son[id]])
son[id]=nxt;
}
return ;
}
inline void dfs2(int id,int tp)
{
dfn[id]=++cnt;
rid[cnt]=id;
top[id]=tp;
if(!son[id])
return ;
dfs2(son[id],tp);
for(auto nxt:e[id])
{
if(nxt==fat[id] || nxt==son[id])
continue;
dfs2(nxt,nxt);
}
return ;
}
inline void swap(int &x,int &y)
{
static int z;
z=x;
x=y;
y=z;
}
inline ll max(ll x,ll y)
{
return x>y?x:y;
}
class node
{
public:
int lv,rv,val,tr,tag;
bool fill;
inline void operator+=(const node &other)
{
tr+=other.tr;
lv=max(lv,tr+other.lv);
rv=max(other.rv,other.tr+rv);
val=max(max(val,other.val),rv+other.lv);
fill=false;
return ;
}
node():lv(0),rv(0),val(0),tr(0),tag(0),fill(false)
{
}
};
node tr[maxn<<2];
inline const node &operator+(const node &x,const node &y)
{
static node ans;
ans=x;
ans+=y;
return ans;
}
inline void build(int id,int l,int r)
{
if(l==r)
{
tr[id].tr=q[rid[l]];
tr[id].lv=tr[id].rv=max(q[rid[l]],0);
return ;
}
build(lc(id),l,mid);
build(rc(id),mid+1,r);
tr[id]=tr[lc(id)]+tr[rc(id)];
}
inline void fill(int id,int l,int r,int k)
{
tr[id].tr=(r-l+1)*k;
tr[id].lv=tr[id].rv=tr[id].val=max(tr[id].tr,0);
tr[id].fill=true;
tr[id].tag=k;
}
inline void push_down(int id,int l,int r)
{
if(tr[id].fill)
{
fill(lc(id),l,mid,tr[id].tag);
fill(rc(id),mid+1,r,tr[id].tag);
tr[id].tag=tr[id].fill=0;
}
return ;
}
inline void update(int id,int ql,int qr,int l,int r,int k)
{
if(ql<=l && r<=qr)
{
fill(id,l,r,k);
return ;
}
push_down(id,l,r);
if(ql<=mid)
update(lc(id),ql,qr,l,mid,k);
if(mid<qr)
update(rc(id),ql,qr,mid+1,r,k);
tr[id]=tr[lc(id)]+tr[rc(id)];
return ;
}
inline const node query(int id,int ql,int qr,int l,int r)
{
if(ql<=l && r<=qr)
return tr[id];
push_down(id,l,r);
node ret;
if(ql<=mid)
ret+=query(lc(id),ql,qr,l,mid);
if(mid<qr)
ret+=query(rc(id),ql,qr,mid+1,r);
return ret;
}
int n;
inline void chg(int x,int y,int k)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{
swap(x,y);
}
update(1,dfn[top[x]],dfn[x],1,n,k);
x=fat[top[x]];
}
if(dep[x]>dep[y])
swap(x,y);
update(1,dfn[x],dfn[y],1,n,k);
return ;
}
inline node query(int x,int y)
{
static node vx,vy,ret,midd;
vx=vy=ret=node();
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{
vy=query(1,dfn[top[y]],dfn[y],1,n)+vy;
y=fat[top[y]];
}else
{
vx=query(1,dfn[top[x]],dfn[x],1,n)+vx;
x=fat[top[y]];
}
}
if(dep[x]>dep[y])
{
vx=query(1,dfn[y],dfn[x],1,n)+vx;
}else
vy=query(1,dfn[x],dfn[y],1,n)+vy;
swap(vx.lv,vx.rv);
return vx+vy;
}
#define rep(i,l,r) for(i=l;i<=r;++i)
int main()
{
int i,m,u,v,opt,l,r,c;
scanf("%d",&n);
rep(i,1,n)
scanf("%d",q+i);
rep(i,1,n-1)
{
scanf("%d %d",&u,&v);
e[u].emplace_back(v);
e[v].emplace_back(u);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
scanf("%d",&m);
rep(i,1,m)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d %d",&l,&r);
printf("%d\n",query(l,r).val);
}else
{
scanf("%d %d %d",&l,&r,&c);
chg(l,r,c);
}
}
return 0;
}