#define NDEBUG

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <cassert>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <random>
using namespace std;
  
typedef long long ll;
struct LCNode {
    typedef LCNode* NP;
    typedef int D;
    static const int INF = 1LL<<25;
    static LCNode last_d;
    static NP last;
    NP p, ch[2];//l, r;
    int sz;
    int v, sm, lz;
    int lsm, rsm, ma, mv;
    bool rev, lzf;
    LCNode(D v) :p(NULL), sz(1),
        v(v), sm(v), rev(false),
        lsm(max(v, 0)), rsm(max(v, 0)), ma(max(v, 0)), mv(v) {
            ch[0] = ch[1] = last;
        }
    LCNode() : sz(0), v(-INF), mv(-INF) {}
    inline int pos() {
        if (p) {
            if (p->ch[0] == this) return 0;
            if (p->ch[1] == this) return 1;
        }
        return -1;
    }
    inline void rot(int ps) {
        NP qq = p->p;
        int pps = p->pos();
//        ps--;
        p->ch[ps] = ch[1-ps]; ch[1-ps]->p = p;
        ch[1-ps] = p; p->p = this;
        p->update(); update();
        p = qq;
        if (pps == -1) return;
        qq->ch[pps] = this;
        qq->update();
    }
    void splay() {
        int ps;
        while ((ps = pos()) != -1) {
            int pps = p->pos();
            if (pps == -1) {
                rot(ps);
            } else if (ps == pps) {
                p->rot(pps); rot(pps);
            } else {
                rot(ps); rot(pps);
            }
        }
    }
    void expose() {
        assert(this != last);
        supush();
        NP u = this, ur = last;
        do {
            u->splay();
            u->ch[1] = ur;
            u->update();
            ur->p = u;
            ur = u;
        } while ((u = u->p));
        splay();
    }
    void push() {
        if (rev) {
            for (int i = 0; i < 2; i++) {
                if (ch[i]->sz) ch[i]->revdata();
            }
//            if (ch[0]->sz) {
//                ch[0]->revdata();
//            }
//            if (ch[1]->sz) {
//                ch[1]->revdata();
//            }
            rev = false;
        }
        if (lzf) {
            if (ch[0]->sz) {
                ch[0]->lzdata(lz);
            }
            if (ch[1]->sz) {
                ch[1]->lzdata(lz);
            }
            lzf = false;
        }
    }
    const static int SS = 200001;
    static NP st[SS];
    static int stc;
    void supush() {
        NP u = this;
        while (u) {
            st[stc++] = u;
            u = u->p;
        }
        while (stc) {
            st[--stc]->push();
        }
    }
    inline void revdata() {
        swap(ch[0], ch[1]);
        swap(lsm, rsm);
        rev ^= true;
    }
    inline void lzdata(D d) {
        v = mv = d;
        sm = sz*d;
        lsm = rsm = ma = max(0, sm);
        lz = d;
        lzf = true;
    }
    NP update() {
        sz = 1; sm = mv = v;
        ma = ch[0]->rsm+v+ch[1]->lsm;
        for (int i = 0; i < 2; i++) {
            sz += ch[i]->sz;
            sm += ch[i]->sm;
            ma = max(ma, ch[i]->ma);
            mv = max(mv, ch[i]->mv);
        }
//        sz = 1+ch[0]->sz+ch[1]->sz;
//        sm = v+ch[0]->sm+ch[1]->sm;
        lsm = max(ch[0]->lsm, ch[0]->sm+v+ch[1]->lsm);
        rsm = max(ch[1]->rsm, ch[1]->sm+v+ch[0]->rsm);
        //ma = ch[0]->rsm+v+ch[1]->lsm;
//        ma = max(ma, ch[0]->ma);
//        ma = max(ma, ch[1]->ma);
//        mv = v;
//        mv = max(mv, ch[0]->mv);
//        mv = max(mv, ch[1]->mv);
        return this;
    }

    void evert() {
        expose();
        revdata();
    }
};
LCNode LCNode::last_d = LCNode();
LCNode::NP LCNode::last = &last_d;
LCNode::NP LCNode::st[LCNode::SS];
int LCNode::stc = 0;

inline int getint() {
    char c;
    int res = 0;
    bool neg = false;
    while (true) {
        c = getchar_unlocked();
        if (c == '-') {
            neg = true;
            break;
        }
        if ('0' <= c && c <= '9') {
            res = c-'0';
            break;
        }
    }
    while (c = getchar_unlocked(), '0' <= c && c <= '9') {
        res *= 10;
        res += c-'0';
    }
    if (neg) res *= -1;
    return res;
}

inline void putint(int d) {
    static char buf[10];
    int c = 0;
    bool neg = false;
    if (d < 0) {
        putchar_unlocked('-');
        d *= -1;
    }
    if (!d) {
        putchar_unlocked('0');
        return;
    }
    while (d) {
        buf[c++] = d%10;
        d = d/10;
    }
    while (c--) {
        putchar_unlocked(buf[c]+'0');
    }
}

const int MN = 200001;
LCNode tr[MN];
int main() {
    int n = getint(), q = getint();
    for (int i = 0; i < n; i++) {
        int w = getint();
        tr[i] = LCNode(w);
    }
    for (int i = 0; i < n-1; i++) {
        int s = getint(), e = getint(); s--; e--;
        tr[s].evert();
        tr[e].expose();
        tr[s].p = tr+e;
    }
    for (int i = 0; i < q; i++) {
        int t = getint(), a = getint(), b = getint(), c = getint();
        a--; b--;
        if (t <= 1) {
            tr[a].evert();
            tr[b].expose();
            tr[b].lzdata(c);
        } else {
            tr[a].evert();
            tr[b].expose();
            int d;
            if (tr[b].mv < 0) d = tr[b].mv;
            else d = tr[b].ma;
            putint(d);
            putchar_unlocked('\n');
        }
    }
}

Measured memory_bytes: 13580