#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;
    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];
    }
    void get_path(int a, int b, function<void(int, int)> f) { // a<-b
        if (a >= 0) a = ord[a];
        if (b >= 0) 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()) {
        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() {
    ios::sync_with_stdio(false); cin.tie(0);
    int n, q;
    cin >> n >> q;
    V<ll> w(n);
    for (int i = 0; i < n; i++) cin >> w[i];
    VV<E> g(n);
    for (int i = 0; i < n-1; i++) {
        int 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);
    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;
        cin >> 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){ 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;
            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);
            cout << (rd + ld).mx << '\n';
        }
    }
    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: 115464