#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<bits/stdc++.h>
using namespace std;
#define int long long
int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' or ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >= '0' and ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}return x * f;}
void write(int x){if(x < 0) putchar('-'), write(-x);else if(x >= 10) write(x/10), putchar(x%10+'0');else putchar(x+'0');}
#define endl puts("")
#define put() putchar(' ')
const int MAX = 1e5+10;
int val[MAX];
vector <int> g[MAX];
struct node{
int s, dl, dr, ans, tag, cov;
void clear(){
s = dl = dr = ans = tag = cov = 0;
}
}; node s[4*MAX];
node pushup(node x, node y){
node re;
re.s = x.s + y.s;
re.dl = max(x.dl, x.s + y.dl);
re.dr = max(y.dr, y.s + x.dr);
re.ans = max(x.ans, max(y.ans, x.dr + y.dl));
re.tag = re.cov = 0;
return re;
}
void upd2(int l, int r, int x, int k){
s[x].s = (r - l + 1) * k;
s[x].dl = s[x].dr = s[x].ans = max(0ll, s[x].s);
s[x].cov = 1, s[x].tag = k;
}
void pushdown(int x, int l, int r){
if(!s[x].cov) return ;
int mid = (l + r) >> 1;
upd2(l, mid, x<<1, s[x].tag);
upd2(mid+1, r, x<<1|1, s[x].tag);
s[x].cov = s[x].tag = 0;
}
node query(int l, int r, int dl, int dr, int x){
if(dl <= l and r <= dr) return s[x];
int mid = (l+r) >> 1;
pushdown(x, l, r);
node ansl, ansr;
ansl.clear(), ansr.clear();
if(mid >= dl) ansl = query(l, mid, dl, dr, x<<1);
if(mid < dr) ansr = query(mid+1, r, dl, dr, x<<1|1);
s[x] = pushup(s[x<<1], s[x<<1|1]);
return pushup(ansl, ansr);
}
void upd(int l, int r, int dl, int dr, int x, int jia){
if(l == r){
upd2(l, r, x, jia);
return ;
}
int mid = (l+r) >> 1;
pushdown(x, l, r);
if(dl <= mid) upd(l, mid, dl, dr, x << 1, jia);
if(dr > mid) upd(mid+1, r, dl, dr, x << 1 | 1, jia);
s[x] = pushup(s[x << 1], s[x << 1 | 1]);
}
int fa[MAX], siz[MAX], dep[MAX], son[MAX];
void dfs1(int u, int father){
fa[u] = father;
siz[u] = 1;
dep[u] = dep[father]+1;
for(int v:g[u]){
if(v == father) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
int dfn[MAX], clk, top[MAX];
int N;
void dfs2(int u, int topu){
dfn[u] = ++clk, top[u] = topu;
if(son[u]) dfs2(son[u], topu);
upd(1, N, dfn[u], dfn[u], 1, val[u]);
for(int v:g[u]){
if(v == fa[u] or v == son[u]) continue;
dfs2(v, v);
}
}
node get(int u, int v){
node ansl, ansr;
ansl.clear(), ansr.clear();
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]){
ansr = pushup(query(1, N, dfn[top[v]], dfn[v], 1), ansr);
v = fa[top[v]];
}else{
ansl = pushup(query(1, N, dfn[top[u]], dfn[u], 1), ansl);
u = fa[top[u]];
}
}
if(dfn[u] > dfn[v]) ansl = pushup(query(1, N, dfn[v], dfn[u], 1), ansl);
else ansr = pushup(query(1, N, dfn[u], dfn[v], 1), ansr);
swap(ansl.dl, ansl.dr);
return pushup(ansl, ansr);
}
void add(int u, int v, int w){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u, v);
upd(1, N, dfn[top[u]], dfn[u], 1, w);
u = fa[top[u]];
}
if(dfn[u] > dfn[v]) swap(u, v);
upd(1, N, dfn[u], dfn[v], 1, w);
}
void solve(){
int n = read();
N = n;
for(int i = 1; i <= n; i++) val[i] = read(), s[i].clear();
for(int i = 1; i < n; i++){
int u = read(), v = read();
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(1, 0);
dfs2(1, 1);
int m = read();
for(int i = 1; i <= m; i++){
int op = read();
if(op == 1){
int u = read(), v = read();
write(get(u, v).ans);
endl;
}else{
int u = read(), v = read(), w = read();
add(u, v, w);
}
}
}
signed main(){
int t = 1;
while(t--) solve();
return 0;
}