#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;

struct data { ll sum, mi, ma, ans; };

void show(data x) {
	cout << x.sum << ' ' << x.mi << ' ' << x.ma << ' ' << x.ans << endl;
}

data f(data x, data y) {
	data z;
	z.sum = x.sum + y.sum;
	z.mi = min(x.mi, x.sum + y.mi);
	z.ma = max(x.ma, x.sum + y.ma);
	z.ans = max(max(x.ans, y.ans), x.sum + y.ma - x.mi);
	return z;
}

struct segtree {
	segtree *lch, *rch;
	int N, val;
	data x;
	segtree(int _N) : N(_N), val(INF), x({0, 0, 0, 0}) {
		if (N == 1) return;
		int n = N / 2;
		lch = new segtree(n);
		rch = new segtree(N - n);
	}
	data get(int l, int r) {
		if (r <= 0 || N <= l) return data{0, INF, -INF, -INF};
		if (l <= 0 && N <= r) return x;
		int n = N / 2;
		if (val != INF) {
			lch->set(0, n, val); rch->set(0, N - n, val);
			val = INF;
		}
		return f(lch->get(l, r), rch->get(l - n, r - n));
	}
	void set(int l, int r, int _val) {
		if (r <= 0 || N <= l) return;
		if (l <= 0 && N <= r) {
			val = _val;
			x = data{N * val, min(0, (N - 1) * val), max(val, N * val), max(val, N * val)};
			return;
		}
		int n = N / 2;
		if (val != INF) {
			lch->set(0, n, val); rch->set(0, N - n, val);
			val = INF;
		}
		lch->set(l, r, _val); rch->set(l - n, r - n, _val);
		x = f(lch->x, rch->x);
	}
};

struct hl_decomp {
	int N, M;
	vector<vi> G;
	vi sz, id, par, dep, dep_l, dep_r;
	vector<segtree*> st1, st2;
	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);
		st1.resize(M); st2.resize(M);
		rep(i, M) {
			st1[i] = new segtree(dep_r[i] - dep_l[i]);
			st2[i] = new segtree(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);
		data z1 = {0, INF, -INF, -INF};
		{
			for (; id[u] != id[w]; u = par[u]) {
				int i = id[u];
				z1 = f(st1[i]->get(0, dep[u] - dep_l[i] + 1), z1);
			}
			int i = id[u];
			z1 = f(st1[i]->get(dep[w] - dep_l[i], dep[u] - dep_l[i] + 1), z1);
		}
		data z2 = {0, INF, -INF, -INF};
		{
			for (; id[v] != id[w]; v = par[v]) {
				int i = id[v];
				z2 = f(z2, st2[i]->get(dep_r[i] - dep[v] - 1, dep_r[i] - dep_l[i]));
			}
			int i = id[v];
			z2 = f(z2, st2[i]->get(dep_r[i] - dep[v] - 1, dep_r[i] - dep[w] - 1));
		}
		return f(z2, z1).ans;
	}
	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];
				st1[i]->set(0, dep[u] - dep_l[i] + 1, val);
				st2[i]->set(dep_r[i] - dep[u] - 1, dep_r[i] - dep_l[i], val);
			}
			int i = id[u];
			st1[i]->set(dep[w] - dep_l[i], dep[u] - dep_l[i] + 1, val);
			st2[i]->set(dep_r[i] - dep[u] - 1, dep_r[i] - dep[w], val);
		}
		{
			for (; id[v] != id[w]; v = par[v]) {
				int i = id[v];
				st1[i]->set(0, dep[v] - dep_l[i] + 1, val);
				st2[i]->set(dep_r[i] - dep[v] - 1, dep_r[i] - dep_l[i], val);
			}
			int i = id[v];
			st1[i]->set(dep[w] - dep_l[i] + 1, dep[v] - dep_l[i] + 1, val);
			st2[i]->set(dep_r[i] - dep[v] - 1, dep_r[i] - dep[w] - 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: 99860