#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>

using namespace std;


const long inf = ((long)1 << 14);

class node
{
public:
	long d;
	long s;
	long b;
	long a;
	long m;
	long n;

	node() = default;

	node(long dw, long k)
	{
		d = dw;
		s = max((long)0, d * k);
		b = max((long)0, d * k);
		a = d * k;
		m = d;
		n = max((long)0, d * k);
	}
};

node unit(node a, node b)
{
	node w;
	w.d = -inf;
	w.s = max(a.s, a.a + b.s);
	w.b = max(b.b, b.a + a.b);
	w.a = a.a + b.a;
	w.m = max(a.m, b.m);
	w.n = max(a.b + b.s, max(a.n, b.n));
	return w;
}

class point
{
public:
	vector<long> f;
	node* seg;
	long dw;
	long o;
	long ob;
	long n;
	long pd;

	point() = default;

	point(long ow, long obw, long pdw)
	{
		o = ow;
		ob = obw;
		pd = pdw;
	}

	void start()
	{
		n = f.size();
		dw = log2(n) + 1;
		seg = (node*)malloc(sizeof(node) * (1 << (dw + 1)));
		for (int i = 0; i < (1 << dw); i++)
		{
			if (i < n)
			{
				seg[(1 << dw) - 1 + i] = node(f[i], 1);
			}
			else
			{
				seg[(1 << dw) - 1 + i] = node(-inf, 1);
			}
		}
		for (int i = (1 << dw) - 2; i >= 0; i--)
		{
			seg[i] = unit(seg[i * 2 + 1], seg[i * 2 + 2]);
		}
	}

	void setw(long p, long b, long e, long nb, long ne, long d)
	{
		if (e <= nb || ne <= b)
		{
			return;
		}
		if (b <= nb && ne <= e)
		{
			seg[p] = node(d, ne - nb);
		}
		else
		{
			if (seg[p].d != -inf)
			{
				seg[p * 2 + 1] = (seg[p * 2 + 2] = node(seg[p].d, (ne - nb) >> 1));
			}
			setw(p * 2 + 1, b, e, nb, (nb + ne) >> 1, d);
			setw(p * 2 + 2, b, e, (nb + ne) >> 1, ne, d);
			seg[p] = unit(seg[p * 2 + 1], seg[p * 2 + 2]);
		}
	}

	void set(long b, long e, long d)
	{
		setw(0, b, e, 0, (1 << dw), d);
	}

	node getw(long p, long b, long e, long nb, long ne)
	{
		if (e <= nb || ne <= b)
		{
			return node(-inf, 0);
		}
		if (b <= nb && ne <= e)
		{
			return seg[p];
		}
		else
		{
			if (seg[p].d != -inf)
			{
				seg[p * 2 + 1] = (seg[p * 2 + 2] = node(seg[p].d, (ne - nb) >> 1));
			}
			return unit(getw(p * 2 + 1, b, e, nb, (nb + ne) >> 1), getw(p * 2 + 2, b, e, (nb + ne) >> 1, ne));
		}
	}

	node get(long b, long e)
	{
		return getw(0, b, e, 0, (1 << dw));
	}
};

point tyo[200000];
long tn;

long myd[200000];
vector<long> hen[200000];
long deep[200000];
long syo[200000];
long syod[200000];

int n, q;

stack<pair<long, long>> st1, st2;

class pw
{
public:
	long now, o, b, nd, pd;

	pw(long noww, long ow, long bw, long ndw, long pdw)
	{
		now = noww;
		o = ow;
		b = bw;
		nd = ndw;
		pd = pdw;
	}
};

stack<pw> st3;

void heavy()
{
	st1.push(make_pair(0, -1));
	while (!st1.empty())
	{
		long b = st1.top().first;
		long o = st1.top().second;
		st2.push(st1.top());
		st1.pop();
		for (auto i : hen[b])
		{
			if (i != o)
			{
				st1.push(make_pair(i, b));
			}
		}
	}
	while (!st2.empty())
	{
		long b = st2.top().first;
		long o = st2.top().second;
		st2.pop();
		long maxw = 0;
		for (auto i : hen[b])
		{
			if (i != o)
			{
				maxw += deep[i];
			}
		}
		deep[b] = max((long)1, maxw);
	}
	tyo[0] = point(-1, -1, 0);
	tn = 1;
	st3.push(pw(0, -1, 0, 0, 0));
	while (!st3.empty())
	{
		long now = st3.top().now;
		long o = st3.top().o;
		long b = st3.top().b;
		long nd = st3.top().nd;
		long pd = st3.top().pd;
		st3.pop();
		tyo[b].f.push_back(myd[now]);
		syo[now] = b;
		syod[now] = nd;
		long maxw = 0;
		for (auto i : hen[now])
		{
			if (i != o)
			{
				maxw = max(maxw, deep[i]);
			}
		}
		bool sude = false;
		for (auto i : hen[now])
		{
			if (i != o)
			{
				if (!sude && deep[i] == maxw)
				{
					st3.push(pw(i, now, b, nd + 1, pd));
					sude = true;
				}
				else
				{
					tyo[tn] = point(b, nd, pd + 1);
					tn++;
					st3.push(pw(i, now, tn - 1, 0, pd + 1));
				}
			}
		}
	}
	for (int i = 0; i < tn; i++)
	{
		tyo[i].start();
	}
}

void set(long a, long b, long d)
{
	long ab = syo[a];
	long bb = syo[b];
	long ad = syod[a];
	long bd = syod[b];
	while (ab != bb)
	{
		if (tyo[ab].pd > tyo[bb].pd)
		{
			tyo[ab].set(0, ad + 1, d);
			ad = tyo[ab].ob;
			ab = tyo[ab].o;
		}
		else
		{
			tyo[bb].set(0, bd + 1, d);
			bd = tyo[bb].ob;
			bb = tyo[bb].o;
		}
	}
	tyo[ab].set(min(ad, bd), max(ad, bd) + 1, d);
}

node rev(node a)
{
	long w = a.s;
	a.s = a.b;
	a.b = w;
	return a;
}

long get(long a, long b)
{
	node aw = node(-inf, 0);
	node bw = node(-inf, 0);
	long ab = syo[a];
	long bb = syo[b];
	long ad = syod[a];
	long bd = syod[b];
	while (ab != bb)
	{
		if (tyo[ab].pd > tyo[bb].pd)
		{
			aw = unit(aw, rev(tyo[ab].get(0, ad + 1)));
			ad = tyo[ab].ob;
			ab = tyo[ab].o;
		}
		else
		{
			bw = unit(bw, rev(tyo[bb].get(0, bd + 1)));
			bd = tyo[bb].ob;
			bb = tyo[bb].o;
		}
	}
	if (bd < ad)
	{
		aw = unit(aw, rev(tyo[ab].get(bd, ad + 1)));
	}
	else
	{
		bw = unit(bw, rev(tyo[ab].get(ad, bd + 1)));
	}
	aw = unit(aw, rev(bw));
	if (aw.m < 0)
	{
		return aw.m;
	}
	else
	{
		return aw.n;
	}
}

int main()
{
	scanf("%d%d", &n, &q);
	for (int i = 0; i < n; i++)
	{
		scanf("%ld", &myd[i]);
	}
	for (int i = 0; i < n - 1; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		a--;
		b--;
		hen[a].push_back(b);
		hen[b].push_back(a);
	}
	heavy();
	for (int i = 0; i < q; i++)
	{
		long t, a, b, c;
		scanf("%ld%ld%ld%ld", &t, &a, &b, &c);
		a--;
		b--;
		if (t == 1)
		{
			set(a, b, c);
		}
		else
		{
			printf("%ld\n", get(a, b));
		}
	}
	return 0;
}

Measured memory_bytes: 80996