#include <bits/stdc++.h>

using namespace std;
using ll = long long;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;

struct HL {
    V<int> _ord, _rord, big, small; //primitive
    V<int> tid, tsz; int tc = 0;
    HL(int n = 0) : _ord(n), _rord(n), big(n), small(n), tid(n) {}
    void init_extra() {
        // ord, rord, big, small以外を使わないなら不要
        int n = int(_ord.size());

        int l = 0;
        while (l < n) {
            int r = l+1;
            while (r < n && small[r] == l) r++;
            tsz.push_back(r-l);
            for (int i = l; i < r; i++) {
                tid[i] = tc;
            }
            l = r;
            tc++;
        }
    }

    int ord(int i) const { return i == -1 ? -1 : _ord[i]; }
    int rord(int i) const { return i == -1 ? -1 : _rord[i]; }
    int par(int a) const {
        a = ord(a);
        return rord(small[a] == a ? big[a] : a-1);
    }
    int lca(int a, int b) const {
        a = ord(a); b = ord(b);
        while (a != b) {
            if (a > b) swap(a, b);
            if (small[b] <= a) break;
            else b = big[b];
        }
        return rord(a);
    }
    template<class F>
    void get_path(int a, int b, F f) const { // [a <- b], 両閉区間
        a = ord(a); b = ord(b);
        while (a < b) {
            if (small[b] <= a) f(a+1, b);
            else f(small[b], b);
            b = big[b];
        }
    }
};

template<class E> struct HL_EXEC : HL {
    const VV<E>& g;
    V<int> tch;
    int id = 0;
    HL_EXEC(const VV<E>& _g, int r) : HL(_g.size()), g(_g), tch(g.size(), -1) {
        assert(dfs_sz(r, -1) == int(g.size()));
        dfs(r, -1);
        init_extra();
    }
    int dfs_sz(int p, int b) {
        int sz = 1, msz = -1;
        for (auto e: g[p]) {
            if (e.to == b) continue;
            int u = dfs_sz(e.to, p);
            sz += u;
            if (msz < u) tie(tch[p], msz) = make_pair(e.to, u);
        }
        return sz;
    }
    void dfs(int p, int b) {
        int q = id++, bq = ord(b);
        _ord[p] = q; _rord[q] = p;
        if (b == -1 || bq != q-1) {
            small[q] = q; big[q] = bq;
        } else {
            small[q] = small[bq]; big[q] = big[bq];
        }
        if (tch[p] == -1) return;
        dfs(tch[p], p);
        for (auto e: g[p]) {
            if (e.to == b || e.to == tch[p]) continue;
            dfs(e.to, p);
        }
    }
};

template<class E> HL get_hl(const VV<E>& g, int r) { return HL_EXEC<E>(g, r); }

struct D {
    ll mx = -TEN(9), l = -TEN(9), r = -TEN(9), sm = 0;
    D operator+(const D& ri) const {
        return D{max({mx, ri.mx, r+ri.l}), max(l, sm+ri.l), max(r+ri.sm, ri.r), sm+ri.sm};
    }
};
struct Node {
    using NP = Node*;
    NP l, r;
    int sz;
    D d; int lz = -TEN(9);
    Node(int _sz) : sz(_sz) {
        if (sz == 1) return;
        l = new Node(sz/2);
        r = new Node(sz - sz/2);
    }
    void lzdata(ll x) {
        if (x >= 0) d = D{x*sz, x*sz, x*sz, x*sz};
        else d = D{x, x, x, x*sz};
        lz = x;
    }
    void push() {
        if (lz == -TEN(9)) return;
        l->lzdata(lz); r->lzdata(lz);
        lz = -TEN(9);
    }
    D get(int a, int b) {
        if (b <= 0 || sz <= a) return D();
        if (a <= 0 && sz <= b) return d;
        push();
        return l->get(a, b) + r->get(a-sz/2, b-sz/2);
    }
    void fil(int a, int b, int x) {
        if (b <= 0 || sz <= a) return;
        if (a <= 0 && sz <= b) {
            lzdata(x);
            return;
        }
        push();
        l->fil(a, b, x); r->fil(a-sz/2, b-sz/2, x); 
        d = l->d + r->d;       
    }
};

struct E { int to; };
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int n, q;
    scanf("%d %d", &n, &q);
    V<ll> w(n);
    for (int i = 0; i < n; i++) scanf("%lld", &(w[i]));
    VV<E> g(n);
    for (int i = 0; i < n-1; i++) {
        int a, b;
        scanf("%d %d", &a, &b); a--; b--;
        g[a].push_back(E{b});
        g[b].push_back(E{a});
    }
    auto hl = get_hl(g, 0);
//    auto tr = new Node(n);
    V<Node*> trs(hl.tc);
    for (int i = 0; i < hl.tc; i++) {
        trs[i] = new Node(hl.tsz[i]);
    }
    for (int i = 0; i < n; i++) {
        int p = hl.ord(i);
        trs[hl.tid[p]]->fil(p - hl.small[p], p - hl.small[p] + 1, w[i]);
    }
    for (int i = 0; i < q; i++) {
        int t, a, b; ll x;
        scanf("%d %d %d %lld", &t, &a, &b, &x); a--; b--;
        int c = hl.lca(a, b);
        int d = hl.par(c);
        if (t == 1) {
            hl.get_path(c, a, [&](int l, int r){
                int id = hl.tid[l], st = hl.small[l];
                trs[id]->fil(l - st, r - st + 1, x);
            });
            hl.get_path(d, b, [&](int l, int r){
                int id = hl.tid[l], st = hl.small[l];
                trs[id]->fil(l - st, r - st + 1, x);
            });
        } else {
            D ld, rd;
            hl.get_path(c, a, [&](int l, int r){
                int id = hl.tid[l], st = hl.small[l];
                ld = trs[id]->get(l - st, r - st + 1) + ld;
            });
            hl.get_path(d, b, [&](int l, int r){
                int id = hl.tid[l], st = hl.small[l];
                rd = trs[id]->get(l - st, r - st + 1) + rd;
            });
            swap(rd.l, rd.r);
            printf("%lld\n", (rd + ld).mx);
        }
    }
    return 0;
}



Measured memory_bytes: 97376