#define _USE_MATH_DEFINES
#include <algorithm>
#include <cstdio>
#include <functional>
#include <iostream>
#include <cfloat>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <vector>
#include <random>
#include <cassert>
using namespace std;
 
#define rep(i, N) for (int i = 0; i < N; i++)
#define pb push_back
 
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> i_i;
typedef pair<ll, int> ll_i;
typedef pair<int, ll> i_ll;
typedef pair<double, int> d_i;
typedef pair<ll, ll> ll_ll;
typedef pair<double, double> d_d;
typedef vector<int> vi;
struct edge { int v; ll w; };
 
const int MOD = 1000000007;
ll _MOD = 1000000009;
double EPS = 1e-10;
ll INF = INT_MAX;

template <class Unko>
struct segtree {
	using T1 = typename Unko::T1;
	using T2 = typename Unko::T2;
	int N, H;
	vector<T1> a;
	vector<T2> b;
	segtree(int _N) {
		for (N = 1, H = 0; N < _N; N *= 2, H++);
		a.assign(N * 2, Unko::_id1());
		b.assign(N * 2, Unko::id2());
	}
	void up(int i) {
		while (i>>=1) {
			T1 xl = Unko::op21(b[i<<1], a[i<<1]);
			T1 xr = Unko::op21(b[i<<1 | 1], a[i<<1 | 1]);
			a[i] = Unko::op11(xl, xr);
		}
	}
	void down(int i0) {
		for (int h = H; h > 0; h--) {
			int i = i0>>h;
			a[i] = Unko::op21(b[i], a[i]);
			b[i<<1] = Unko::op22(b[i], b[i<<1]);
			b[i<<1 | 1] = Unko::op22(b[i], b[i<<1 | 1]);
			b[i] = Unko::id2();
		}
	}
	T1 get(int l, int r) {
		if (l == r) return Unko::id1();
		l += N; r += N;
		down(l); down(r - 1);
		T1 xl = Unko::id1(), xr = Unko::id1();
		for (; l < r; l>>=1, r>>=1) {
			if (l & 1) xl = Unko::op11(xl, Unko::op21(b[l], a[l])), l++;
			if (r & 1) r--, xr = Unko::op11(Unko::op21(b[r], a[r]), xr);
		}
		return Unko::op11(xl, xr);
	}
	void set(int l0, int r0, T2 y) {
		if (l0 == r0) return;
		l0 += N; r0 += N;
		down(l0); down(r0 - 1);
		for (int l = l0, r = r0; l < r; l>>=1, r>>=1) {
			if (l & 1) b[l] = Unko::op22(y, b[l]), l++;
			if (r & 1) r--, b[r] = Unko::op22(y, b[r]);
		}
		up(l0); up(r0 - 1);
	}
};

struct hoge { int d; ll ma, sum, pre, suf, ans; };

struct unko {
	using T1 = hoge;
	using T2 = int;
	static T1 id1() { return {0, -INF, 0, 0, 0, 0}; }
	static T1 _id1() { return {1, -INF, 0, 0, 0, 0}; }
	static T2 id2() { return 114514; }
	static T1 op11(const T1 &xl, const T1 &xr) {
		return {
			xl.d + xr.d,
			max(xl.ma, xr.ma),
			xl.sum + xr.sum,
			max(xl.pre, xl.sum + xr.pre),
			max(xl.suf + xr.sum, xr.suf),
			max(max(xl.ans, xr.ans), xl.suf + xr.pre)
		};
	}
	static T1 op21(const T2 &y, const T1 &x) {
		return y == 114514 ? x : hoge{
			x.d,
			y,
			x.d * y,
			x.d * max(0, y),
			x.d * max(0, y),
			x.d * max(0, y)
		};
	}
	static T2 op22(const T2 &yl, const T2 &yr) {
		return yl == 114514 ? yr : yl;
	}
};

struct hl_decomp {
    int N, M;
    vector<vi> G;
    vi sz, id, par, dep, dep_l, dep_r;
    vector<segtree<unko>*> st;
    hl_decomp(int _N, vector<vi> _G)
        : N(_N), G(_G), sz(N), id(N), par(N), dep(N) {
        dfs_sz(0, -1);
        dfs_decomp(0, -1);
        M = 1; par[0] = -1; dfs_decomp(0, -1);
        dep_l.assign(M, N); dep_r.assign(M, 0); dfs_dep(0, -1);
        st.resize(M);
        rep(i, M) st[i] = new segtree<unko>(dep_r[i] - dep_l[i]);
    }
    void dfs_sz(int u, int p) {
        sz[u] = 1;
        for (int v: G[u]) if (v != p) {
            dfs_sz(v, u);
            sz[u] += sz[v];
        }
    }
    void dfs_decomp(int u, int p) {
        int v0 = -1;
        for (int v: G[u]) if (v != p)
            if (v0 == -1 || sz[v] > sz[v0]) v0 = v;
        for (int v: G[u]) if (v != p) {
            if (v == v0) {
                id[v] = id[u];
                par[v] = par[u];
            }
            else {
                id[v] = M++;
                par[v] = u;
            }
            dfs_decomp(v, u);
        }
    }
    void dfs_dep(int u, int p) {
        int i = id[u];
        dep_l[i] = min(dep_l[i], dep[u]);
        dep_r[i] = max(dep_r[i], dep[u] + 1);
        for (int v: G[u]) if (v != p) {
            dep[v] = dep[u] + 1;
            dfs_dep(v, u);
        }
    }
    int lca(int u, int v) {
        while (id[u] != id[v]) {
            int _u = par[u], _v = par[v];
            if (_u == -1) v = _v;
            else if (_v == -1) u = _u;
            else if (dep[_u] >= dep[_v]) u = _u;
            else v = _v;
        }
        return dep[u] < dep[v] ? u : v;
    }
    ll get(int u, int v) {
        int w = lca(u, v);
        hoge z1 = {0, -INF, 0, 0, 0, 0};
        {
            for (; id[u] != id[w]; u = par[u]) {
                int i = id[u];
                z1 = unko::op11(st[i]->get(0, dep[u] - dep_l[i] + 1), z1);
            }
            int i = id[u];
            z1 = unko::op11(st[i]->get(dep[w] - dep_l[i], dep[u] - dep_l[i] + 1), z1);
        }
        hoge z2 = {0, -INF, 0, 0, 0, 0};
        {
            for (; id[v] != id[w]; v = par[v]) {
                int i = id[v];
                z2 = unko::op11(st[i]->get(0, dep[v] - dep_l[i] + 1), z2);
            }
            int i = id[v];
            z2 = unko::op11(st[i]->get(dep[w] - dep_l[i] + 1, dep[v] - dep_l[i] + 1), z2);
        }
		swap(z2.pre, z2.suf);
        hoge z = unko::op11(z2, z1);
		return z.ans ? z.ans : z.ma;
    }
    void set(int u, int v, int val) {
        int w = lca(u, v);
        {
            for (; id[u] != id[w]; u = par[u]) {
                int i = id[u];
                st[i]->set(0, dep[u] - dep_l[i] + 1, val);
            }
            int i = id[u];
            st[i]->set(dep[w] - dep_l[i], dep[u] - dep_l[i] + 1, val);
        }
        {
            for (; id[v] != id[w]; v = par[v]) {
                int i = id[v];
                st[i]->set(0, dep[v] - dep_l[i] + 1, val);
            }
            int i = id[v];
            st[i]->set(dep[w] - dep_l[i] + 1, dep[v] - dep_l[i] + 1, val);
        }
    }
};
 
int main() {
    int N, Q; cin >> N >> Q;
    vector<int> a(N);
    rep(u, N) scanf("%d", &a[u]);
    vector<vector<int> > G(N);
    rep(i, N - 1) {
        int u, v; scanf("%d%d", &u, &v);
        u--; v--;
        G[u].pb(v); G[v].pb(u);
    }
    hl_decomp hl(N, G);
    rep(u, N) hl.set(u, u, a[u]);
    while (Q--) {
        int q, u, v, w;
        scanf("%d%d%d%d", &q, &u, &v, &w);
        u--; v--;
        if (q == 1) hl.set(u, v, w);
        if (q == 2) printf("%lld\n", hl.get(u, v));
    }
}

Measured memory_bytes: 85764