#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, l, r;
    int sz;
    int v, sm, lz;
    int lsm, rsm, ma, mv;
    bool rev, lzf;
    LCNode(D v) :p(NULL), l(last), r(last), sz(1),
        v(v), sm(v), rev(false),
        lsm(max(v, 0)), rsm(max(v, 0)), ma(max(v, 0)), mv(v) {}
    LCNode() : l(NULL), r(NULL), sz(0), v(-INF), mv(-INF) {}
    inline int pos() {
        if (p) {
            if (p->l == this) return -1;
            if (p->r == this) return 1;
        }
        return 0;
    }
    inline void rot() {
        NP qq = p->p;
        int pps = p->pos();
        if (p->l == this) {
            p->l = r; r->p = p;
            r = p; p->p = this;
        } else {
            p->r = l; l->p = p;
            l = p; p->p = this;
        }
        p->update(); update();
        p = qq;
        if (!pps) return;
        if (pps == -1) {
            qq->l = this;
        } else {
            qq->r = this;
        }
        qq->update();
    }
    void splay() {
        assert(this != last);
        supush();
        int ps;
        while ((ps = pos())) {
            int pps = p->pos();
            if (!pps) {
                rot();
            } else if (ps == pps) {
                p->rot(); rot();
            } else {
                rot(); rot();
            }
        }
    }
    void expose() {
        assert(this != last);
        NP u = this;
        do {
            u->splay();
        } while ((u = u->p));
        u = last;
        u->p = this;
        do {
            u->p->r = u;
            u->p->update();
            u = u->p;
        } while (u->p);
        splay();
    }
    void push() {
        int lsz = l->sz, rsz = r->sz;
        if (lsz) {
            if (rev) {
                l->revdata();
            }
            if (lzf) {
                l->lzdata(lz);
            }
        }
        if (rsz) {
            if (rev) {
                r->revdata();
            }
            if (lzf) {
                r->lzdata(lz);
            }
        }
        rev = lzf = false;
        /*
        if (rev) {
            if (lsz) {
                l->revdata();
            }
            if (rsz) {
                r->revdata();
            }
            rev = false;
        }
        if (lzf) {
            if (lsz) {
                l->lzdata(lz);
            }
            if (rsz) {
                r->lzdata(lz);
            }
            lzf = false;
        }*/
    }
    void nopush() {
        assert(!rev);
        assert(!lzf);
    }
    void supush() {
        if (pos()) {
            p->supush();
        }
        push();
    }
    inline void revdata() {
        assert(this != last);
        swap(l, r);
        swap(lsm, rsm);
        rev ^= true;
    }
    inline void lzdata(D d) {
        assert(this != last);
        v = mv = d;
        sm = sz*d;
        lsm = rsm = ma = max(0, sm);
        lz = d;
        lzf = true;
    }
    NP update() {
        assert(this != last);
        sz = 1+l->sz+r->sz;
        sm = v+l->sm+r->sm;
        lsm = max(l->lsm, l->sm+v+r->lsm);
        rsm = max(r->rsm, r->sm+v+l->rsm);
        ma = l->rsm+v+r->lsm;
        ma = max(ma, l->ma);
        ma = max(ma, r->ma);
        mv = v;
        mv = max(mv, l->mv);
        mv = max(mv, r->mv);
        return this;
    }

    void evert() {
        expose();
        revdata();
    }
};
LCNode LCNode::last_d = LCNode();
LCNode::NP LCNode::last = &last_d;

const int BS = 1<<20;
const int OBS = 1<<20;
char stdinb[BS], stdoutb[OBS], convb[20];
int sinc = BS, soutc = 0;
inline char getc() {
    if (sinc == BS) {
        read(0, stdinb, BS);
        sinc = 0;
    }
    sinc++;
    return stdinb[sinc-1];
}
int getint() {
    char c;
    bool neg = false;
    do {
        c = getc();
    } while (!isdigit(c) && c != '-');
    if (c == '-') {neg = true; c = getc();}
    int res = c-'0';
    while (isdigit(c = getc())) {
        res *= 10;
        res += c-'0';
    }
    if (neg) res *= -1;
    return res;
}
inline void putc(char c) {
    stdoutb[soutc] = c;
    soutc++;
    if (soutc == OBS) {
        write(1, stdoutb, OBS);
        soutc = 0;
    }
}
void flush() {
    write(1, stdoutb, soutc);
    soutc = 0;
}
void putint(int d) {
    int c = 0;
    bool neg = false;
    if (d < 0) {
        putc('-');
        d *= -1;
    }
    if (!d) {
        putc('0');
        return;
    }
    while (d) {
        auto u = div(d, 10);
        convb[c] = u.rem + '0';
        d = u.quot;
        c++;
    }
    while (c > 0) {
        putc(convb[c-1]); c--;
    }
}

const int MN = 201000;
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);
            putc('\n');
        }
    }
    flush();
}

Measured memory_bytes: 15652