#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>>;

using P = pair<int, int>;
struct HL {
    V<int> _ord, _rord, big, small;
    HL(int n = 0) : _ord(n), _rord(n), big(n), small(n) {}
    int ord(int i) { return i == -1 ? -1 : _ord[i]; }
    int rord(int i) { return i == -1 ? -1 : _rord[i]; }
    int par(int a) {
        a = ord(a);
        return rord(small[a] == a ? big[a] : a-1);
    }
    int lca(int a, int b) {
        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);
    }
    void get_path(int a, int b, function<void(int, int)> f) { // 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];
        }
    }
    V<P> get_path(int a, int b) {
        a = ord(a); b = ord(b);
        V<P> res;
        while (a < b) {
            if (small[b] <= a) res.push_back(P(a+1, b+1));
            else res.push_back(P(small[b], b+1));
            b = big[b];
        }
        return res;
    }
};
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);
    }
    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, V<ll> &fi, int off = 0) : sz(_sz) {
        if (sz == 1) {
            lzdata(fi[off]);
            return;
        }
        l = new Node(sz/2, fi, off);
        r = new Node(sz - sz/2, fi, off + sz/2);
        d = l->d + r->d;
    }
    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);
    }
    D get_multi(V<P> &q, int off = 0) {
        while (q.size() && q.back().second <= off) q.pop_back();
        if (!q.size() || off+sz <= q.back().first) return D();
        if (q.back().first <= off && off+sz <= q.back().second) return d;
        push();
        D ld = l->get_multi(q, off);
        D rd = r->get_multi(q, off + sz/2);
        return ld + rd;
    }
    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;       
    }
    void fil_multi(V<P> &q, int x, int off = 0) {
        while (q.size() && q.back().second <= off) q.pop_back();
        if (!q.size() || off+sz <= q.back().first) return;
        if (q.back().first <= off && off+sz <= q.back().second) {
            lzdata(x);
            return;
        }
        push();
        l->fil_multi(q, x, off);
        r->fil_multi(q, x, off + sz/2);
        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);
//    cin >> n >> q;
    V<ll> w(n), w2(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--;
//        cin >> a >> b; a--; b--;
        g[a].push_back(E{b});
        g[b].push_back(E{a});
    }
    auto hl = get_hl(g, 0);    
    for (int i = 0; i < n; i++) w2[i] = w[hl.rord(i)];
    auto tr = new Node(n, w2);
    for (int i = 0; i < q; i++) {
        int t, a, b; ll x;
        scanf("%d %d %d %lld", &t, &a, &b, &x); a--; b--;
//        cin >> t >> a >> b >> x; a--; b--;
        int c = hl.lca(a, b);
        int d = hl.par(c);
        if (t == 1) {
            V<P> lq = hl.get_path(c, a), rq = hl.get_path(d, b);
            tr->fil_multi(lq, x);
            tr->fil_multi(rq, x);
//            hl.get_path(c, a, [&](int l, int r){ tr->fil(l, r+1, x); });
//            hl.get_path(d, b, [&](int l, int r){ tr->fil(l, r+1, x); });
        } else {
            D ld, rd;
            V<P> lq = hl.get_path(c, a), rq = hl.get_path(d, b);
            ld = tr->get_multi(lq);
            rd = tr->get_multi(rq);
//            hl.get_path(c, a, [&](int l, int r){ ld = tr->get(l, r+1) + ld; });
//            hl.get_path(d, b, [&](int l, int r){ rd = tr->get(l, r+1) + rd; });
            swap(rd.l, rd.r);
            printf("%lld\n", (rd + ld).mx);
//            cout << (rd + ld).mx << '\n';
        }
    }
    return 0;
}



Measured memory_bytes: 98260