#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, q;
int a[N];
vector<int> vec[N];
int dfn[N], rnk[N], fa[N], son[N], top[N], deep[N], size[N], cnt;
void dfs1(int u, int F, int d) {
fa[u] = F;
deep[u] = d;
size[u] = 1;
int ma = 0;
for(int v : vec[u]) {
if(v == F) continue;
dfs1(v, u, d + 1);
size[u] += size[v];
if(ma < size[v]) {
ma = size[v];
son[u] = v;
}
}
return ;
}
void dfs2(int u, int F, int s) {
if(s) {
top[u] = top[F];
} else {
top[u] = u;
}
dfn[u] = ++ cnt;
rnk[cnt] = u;
if(son[u]) {
dfs2(son[u], u, 1);
}
for(int v : vec[u]) {
if(v == F) continue;
if(v == son[u]) continue;
dfs2(v, u, 0);
}
return ;
}
struct node {
int sum, lmax, rmax, ans;
node() {
sum = lmax = rmax = ans = 0;
}
node(int s, int l, int r, int a) {
sum = s;
lmax = l;
rmax = r;
ans = a;
return ;
}
const node operator+(const node a) {
return node(sum + a.sum, max(lmax, sum + a.lmax), max(a.rmax, a.sum + rmax), max(ans, max(a.ans, rmax + a.lmax)));
}
} ;
struct sgt {
node tree[N << 2];
int b[N << 2];
void pushup(int p) {
tree[p] = tree[p << 1] + tree[p << 1 | 1];
return ;
}
void set(int l, int r, int p, int val) {
int sum = (r - l + 1) * val;
if(val < 0) {
tree[p] = {sum, 0, 0, 0};
} else {
tree[p] = {sum, sum, sum, sum};
}
return ;
}
void pushdown(int l, int r, int p) {
int mid = (l + r) >> 1;
set(l, mid, p << 1, b[p]);
set(mid + 1, r, p << 1 | 1, b[p]);
b[p << 1] = b[p];
b[p << 1 | 1] = b[p];
b[p] = 0;
return ;
}
void build(int l, int r, int p) {
if(l == r) {
set(l, r, p, a[rnk[l]]);
return ;
}
int mid = (l + r) >> 1;
build(l, mid, p << 1);
build(mid + 1, r, p << 1 | 1);
pushup(p);
return ;
}
void change(int l, int r, int s, int t, int p, int val) {
if(t < l || r < s) return ;
if(l <= s && t <= r) {
set(s, t, p, val);
b[p] = val;
return ;
}
if(b[p]) pushdown(s, t, p);
int mid = (s + t) >> 1;
change(l, r, s, mid, p << 1, val);
change(l, r, mid + 1, t, p << 1 | 1, val);
pushup(p);
return ;
}
node get(int l, int r, int s, int t, int p) {
if(t < l || r < s) return node();
if(l <= s && t <= r) {
return tree[p];
}
if(b[p]) pushdown(s, t, p);
int mid = (s + t) >> 1;
return get(l, r, s, mid, p << 1) + get(l, r, mid + 1, t, p << 1 | 1);
}
} sgt;
int get(int a, int b) {
node resa, resb;
while(top[a] != top[b]) {
if(deep[top[a]] < deep[top[b]]) {
resb = sgt.get(dfn[top[b]], dfn[b], 1, n, 1) + resb;
b = fa[top[b]];
} else {
resa = sgt.get(dfn[top[a]], dfn[a], 1, n, 1) + resa;
a = fa[top[a]];
}
}
if(deep[a] < deep[b]) {
resb = sgt.get(dfn[a], dfn[b], 1, n, 1) + resb;
} else {
resa = sgt.get(dfn[b], dfn[a], 1, n, 1) + resa;
}
swap(resa.lmax, resa.rmax);
return (resa + resb).ans;
}
void change(int a, int b, int val) {
while(top[a] != top[b]) {
if(deep[top[a]] < deep[top[b]]) {
swap(a, b);
}
sgt.change(dfn[top[a]], dfn[a], 1, n, 1, val);
a = fa[top[a]];
}
if(deep[a] < deep[b]) {
swap(a, b);
}
sgt.change(dfn[b], dfn[a], 1, n, 1, val);
return ;
}
signed main() {
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
}
for(int i = 1; i < n; i ++) {
int u, v;
cin >> u >> v;
vec[u].push_back(v);
vec[v].push_back(u);
}
dfs1(1, 0, 1);
dfs2(1, 0, 0);
sgt.build(1, n, 1);
cin >> q;
while(q --) {
int op, a, b, v;
cin >> op >> a >> b;
if(op == 1) {
printf("%d\n", get(a, b));
} else {
cin >> v;
change(a, b, v);
}
}
return 0;
}