rt
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxn 100005
using namespace std;
typedef long long ll;
int read() {
int x = 0, f = 1, ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
return x * f;
}
struct edge {int to, nxt;} e[maxn << 1];
int head[maxn], k = 0;
void add(int u, int v) {e[k] = {v, head[u]}; head[u] = k++;}
int n, q, a[maxn];
int fa[maxn], son[maxn], size[maxn], dep[maxn], top[maxn], dfn[maxn], tot = 0, id[maxn];
int t[maxn << 2], lx[maxn << 2], rx[maxn << 2], sum[maxn << 2], flag[maxn << 2];
struct node {int t, lx, rx, sum;};
node operator + (node a, node b) {
node res = {0, 0, 0, 0};
res.lx = max(a.lx, a.sum + b.lx);
res.rx = max(b.rx, b.sum + a.rx);
res.sum = a.sum + b.sum;
res.t = max(a.t, b.t);
res.t = max(res.t, a.rx + b.lx);
res.t = max(res.t, max(res.lx, res.rx));
return res;
}
struct SegT {
void update(int p) {
lx[p] = max(lx[p << 1], sum[p << 1] + lx[p << 1 | 1]);
rx[p] = max(rx[p << 1 | 1], sum[p << 1 | 1] + rx[p << 1]);
sum[p] = sum[p << 1] + sum[p << 1 | 1];
t[p] = max(t[p << 1], t[p << 1 | 1]);
t[p] = max(t[p], rx[p << 1] + lx[p << 1 | 1]);
t[p] = max(t[p], max(lx[p], rx[p]));
}
void up(int p, int l, int r, int x) {
t[p] = lx[p] = rx[p] = sum[p] = (r - l + 1) * x;
if(t[p] < 0) t[p] = lx[p] = rx[p] = 0;
flag[p] = x;
}
void build(int p, int l, int r) {
if(l == r) {t[p] = lx[p] = rx[p] = sum[p] = a[id[l]]; if(t[p] < 0) t[p] = lx[p] = rx[p] = 0; return;}
register int mid = l + r >> 1;
build(p << 1, l, mid); build(p << 1 | 1, mid + 1, r);
update(p);
}
void change(int p, int l, int r, int ls, int rs, int x) {
if(ls <= l && r <= rs) {
// printf("change %d %d\n", id[l], id[r]);
if(x >= 0) t[p] = x, lx[p] = rx[p] = sum[p] = (r - l + 1) * x;
else t[p] = lx[p] = rx[p] = 0, sum[p] = (r - l + 1) * x;
flag[p] = x; return;
}
register int mid = l + r >> 1;
if(flag[p]) up(p << 1, l, mid, flag[p]), up(p << 1 | 1, mid + 1, r, flag[p]), flag[p] = 0;
if(ls <= mid) change(p << 1, l, mid, ls, rs, x);
if(rs > mid) change(p << 1 | 1, mid + 1, r, ls, rs, x);
update(p);
}
node ask(int p, int l, int r, int ls, int rs) {
if(ls <= l && r <= rs) return {t[p], lx[p], rx[p], sum[p]};
register int mid = l + r >> 1; node ans = {0, 0, 0, 0};
if(flag[p]) up(p << 1, l, mid, flag[p]), up(p << 1 | 1, mid + 1, r, flag[p]), flag[p] = 0;
if(ls <= mid) ans = ans + ask(p << 1, l, mid, ls, rs);
if(rs > mid) ans = ans + ask(p << 1 | 1, mid + 1, r, ls, rs);
return ans;
}
}T;
struct HLD {
void dfs1(int u) {
size[u] = 1;
for(int i = head[u], v; ~i; i = e[i].nxt) if(e[i].to ^ fa[u]) {
v = e[i].to; fa[v] = u; dep[v] = dep[u] + 1;
dfs1(v); size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
dfn[u] = ++tot; top[u] = tp; id[tot] = u;
if(son[u]) dfs2(son[u], tp);
for(int i = head[u], v; ~i; i = e[i].nxt)
if((e[i].to ^ fa[u]) && (e[i].to ^ son[u])) dfs2(e[i].to, e[i].to);
}
void modify(int u, int v, int x) {
while(top[u] != top[v]) {
if(dep[top[u]] > dep[top[v]]) swap(u, v);
T.change(1, 1, n, dfn[top[v]], dfn[v], x); v = fa[top[v]];
}
if(dep[u] > dep[v]) swap(u, v);
T.change(1, 1, n, dfn[u], dfn[v], x);
}
int query(int u, int v) {
node res1 = {0, 0, 0, 0}, res2 = {0, 0, 0, 0};
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) res1 = T.ask(1, 1, n, dfn[top[v]], dfn[v]) + res1, v = fa[top[v]];
else res2 = T.ask(1, 1, n, dfn[top[u]], dfn[u]) + res2, u = fa[top[u]];
}
// printf("ask %d %d\n", u, v);
if(dep[u] < dep[v]) res1 = T.ask(1, 1, n, dfn[u], dfn[v]) + res1;
else res2 = T.ask(1, 1, n, dfn[v], dfn[u]) + res2;
swap(res2.lx, res2.rx);
res1 = res2 + res1;
return res1.t;
}
}H;
signed main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
n = read(); memset(head, -1, sizeof head);
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1, u, v; i < n; i++) u = read(), v = read(), add(u, v), add(v, u);
H.dfs1(1); H.dfs2(1, 1);
T.build(1, 1, n);
q = read();
while(q--) {
register int op = read(), l = read(), r = read(), x;
if(op == 1) printf("%d\n", H.query(l, r));
else x = read(), H.modify(l, r, x);
}
return 0;
}