#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 Pi = pair<int, int>;
struct HL {
    V<int> ord, rord, big, small;
    HL(int n = 0) : ord(n), rord(n), big(n), small(n) {}
    int par(int a) {
        a = ord[a];
        a = (small[a] == a ? big[a] : a-1);
        return (a == -1) ? -1 : rord[a];
    }
    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];
    }
    V<Pi> get_path(int a, int b) { // a<-b
        if (a >= 0) a = ord[a];
        if (b >= 0) b = ord[b];
        V<Pi> res;
        while (a < b) {
            if (small[b] <= a) res.push_back(Pi(a+1, b));
            else res.push_back(Pi(small[b], b));
            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()) {
        assert(dfs_sz(r, -1) == g.size());
        dfs(r, -1, -1, 0);
        for (int i = 0; i < g.size(); i++) rord[ord[i]] = i;
    }
    int dfs_sz(int p, int b) {
        int sz = 1;
        int m = -1, msz = -1;
        for (auto e: g[p]) {
            if (e.to == b) continue;
            int u = dfs_sz(e.to, p);
            sz += u;
            if (m == -1 || msz < u) tie(m, msz) = make_pair(e.to, u);
        }
        tch[p] = m;
        return sz;
    }
    void dfs(int p, int b, int bg, int sm) {
        int q = id++;
        ord[p] = q; big[q] = bg; small[q] = sm;
        if (tch[p] == -1) return;
        dfs(tch[p], p, bg, sm);
        for (auto e: g[p]) {
            if (e.to == b || e.to == tch[p]) continue;
            dfs(e.to, p, q, id);
        }
    }
};
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 main2() {
    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);
    for (int i = 0; i < n; i++) tr->fil(i, i+1, w[hl.rord[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);
        V<Pi> lq = hl.get_path(hl.par(c), a), rq = hl.get_path(c, b);
        // cout << a << " " << b << " " << c << endl;
        // for (auto pi: lq) cout << "(" << pi.first << " " << pi.second << "), "; cout << endl;
        // for (auto pi: rq) cout << "(" << pi.first << " " << pi.second << "), "; cout << endl;
        if (t == 1) {
            for (auto pi: lq) tr->fil(pi.first, pi.second + 1, x);
            for (auto pi: rq) tr->fil(pi.first, pi.second + 1, x);
        } else {
            D ld, rd;
            for (auto pi: lq) ld = tr->get(pi.first, pi.second + 1) + ld;
            for (auto pi: rq) rd = tr->get(pi.first, pi.second + 1) + rd;
            // cout << "DE1 " << ld.mx << " " << ld.l << " " << ld.r << " " << ld.sm << endl;
            // cout << "DE2 " << rd.mx << " " << rd.l << " " << rd.r << " " << rd.sm << endl;
            swap(rd.l, rd.r);
            cout << (rd + ld).mx << endl;
        }
    }
    return 0;
}

// stack sizeを拡張する 64bit用
int main() {
    static ll eord, enew;
    const int sz = 256*1024*1024;
    static unsigned char *p = (unsigned char*)malloc(sz);
    enew = ((ll)(p+sz-1) & ~0xff);
    __asm__ volatile("mov %%rsp, %0" : "=r"(eord));
    __asm__ volatile("mov %0, %%rsp" : : "r"(enew));
    main2();
    __asm__ volatile("mov %0, %%rsp" : : "r"(eord));
    return 0;
}


Measured memory_bytes: 115360