#define NDEBUG
#include <iostream>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <vector>
#include <valarray>
#include <array>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <complex>
#include <random>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;

/**
 * ??¨???????????????????????????????????¨?????????Link-Cut Tree
 *
 * ????????¨????????????link???cut???evert???root???????£???????
 * ?????????????????????????????´???????????????????????¨?\¨??????
 * 
 * ??¶?????????????????¨?????????????£?????????°?????????????????§?????¨???????????\???????????????????????????
 * ??????????????????????£??????§????´?2k(????????????)??§???ICPC??§????????¨???????????????
 */
struct LCNode {
    typedef LCNode* NP;

    typedef int D;
    struct Node {
        D v, ma, lma, rma, oma, sm;
        D lz; bool lzf;
    } n;
    LCNode() : l(nullptr), r(nullptr), sz(0), rev(false) {
        n.v = -100000;
        n.ma = 0;
        n.lma = 0;
        n.rma = 0;
        n.oma = -100000;
        n.sm = 0;
        n.lzf = false;
    }
    LCNode(D v) : p(nullptr), l(last), r(last), sz(1), rev(false) {
        n.v = v;
        n.ma = max(0, v);
        n.lma = max(0, v);
        n.rma = max(0, v);
        n.oma = v;
        n.sm = v;
        n.lzf = false;
    }

    NP update() {
        assert(this != last);
        sz = 1+l->sz+r->sz;
        n.ma = l->n.rma+n.v+r->n.lma;
        n.ma = max(n.ma, l->n.ma);
        n.ma = max(n.ma, r->n.ma);
        n.lma = max(l->n.lma, l->n.sm+n.v+r->n.lma);
        n.rma = max(l->n.rma+n.v+r->n.sm, r->n.rma);
        n.oma = n.v;
        n.oma = max(n.oma, l->n.oma);
        n.oma = max(n.oma, r->n.oma);
        n.sm = l->n.sm+n.v+r->n.sm;
        return this;
    }
    void push() {
        int lsz = l->sz, rsz = r->sz;
        if (n.lzf) {
            if (lsz) {
                l->lzdata(n.lz);
            }
            if (rsz) {
                r->lzdata(n.lz);
            }
            n.lzf = false;
        }
        if (rev) {
            if (lsz) {
                l->revdata();
            }
            if (rsz) {
                r->revdata();
            }
            rev = false;
        }
    }
    void lzdata(D v) {
        n.v = v;
        n.ma = max(0, sz*v);
        n.lma = max(0, sz*v);
        n.rma = max(0, sz*v);
        n.oma = v;
        n.sm = sz*v;
        n.lz = v;
        n.lzf = true;
    }
    void revdata() {
        assert(this != last);
        swap(l, r);
        swap(n.lma, n.rma);
        rev ^= true;
    }
    D get() {
        expose();
        if (n.oma < 0) return n.oma;
        return n.ma;
    }
    void set(D d) {
        expose();
        lzdata(d);
    }

    //????????????
    static LCNode last_d;
    static NP last;
    NP p, l, r;
    int sz;
    bool rev;
    inline int pos() {
        if (p) {
            if (p->l == this) return -1;
            if (p->r == this) return 1;
        }
        return 0;
    }
    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, ur = last;
        do {
            u->splay();
            u->r = ur;
            u->update();
            ur = u;
        } while ((u = u->p));
        splay();
    }
    /**
     * splay?????????????????¬??§???????????????????????¨???????????§???push??????
     * ??????stack overflow???????????¢??°????????§??¨??????????????¨
     */
    void supush() {
        if (pos()) {
            p->supush();
        }
        push();
    }
    //???????????§?????¶?????????

    void link(NP r) {
        assert(this != r);
        expose();
        r->expose();
        assert(l == last);
        p = r;
    }

    void cut() {
        expose();
        l->p = NULL;
        l = last;
        update();
    }

    NP root() {
        expose();
        NP u = this;
        while (u->l != last) {
            u = u->l;
            u->push();
        }
        u->expose(); //????????????????????¨?¨????????????????????????????
        return u;
    }

    void evert() {
        expose();
        revdata();
    }

    NP lca(NP n) {
        n->expose();
        expose();
        NP t = n;
        while (n->p != nullptr) {
            if (!n->pos()) t = n->p;
            n = n->p;
        }
        return (this == n) ? t : nullptr;
    }
};
LCNode LCNode::last_d = LCNode();
LCNode::NP LCNode::last = &last_d;

const int MN = 200100;
LCNode tr[MN];
int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 0; i < n; i++) {
        int d;
        scanf("%d", &d);
        tr[i] = LCNode(d);
    }
    for (int i = 0; i < n-1; i++) {
        int a, b;
        scanf("%d %d", &a, &b); a--; b--;
        tr[a].evert();
        tr[a].link(&tr[b]);
    }
    for (int i = 0; i < m; i++) {
        int t, a, b, c;
        scanf("%d %d %d %d", &t, &a, &b, &c); a--; b--;
        if (t == 1) {
            tr[a].evert();
            tr[b].set(c);
        } else {
            tr[a].evert();
            printf("%d\n", tr[b].get());
        }
    }
    return 0;
}

Measured memory_bytes: 13688