#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;

typedef long long ll;
const ll inf = 1LL<<35;
const int maxn = 400010;
int N,Q,side[maxn],nxt[maxn],redfn[maxn],top[maxn],size[maxn];
int cnt,timestamp,dep[maxn],father[maxn],dfn[maxn],toit[maxn],w[maxn];

struct Node
{
	ll sum,ls,rs,best; 
	inline Node():sum(0),ls(-inf),rs(-inf),best(-inf) {}
	inline Node(ll x):sum(x),ls(x),rs(x),best(x) {}
	inline void set(ll x,int len)
	{
		sum = x*len;
		ls = rs = max(x,sum);
		best = max(x,sum);
	}
	friend inline Node operator +(const Node &a,const Node &b)
	{
		Node ret;
		ret.sum = a.sum+b.sum;
		ret.ls = max(a.ls,a.sum+b.ls);
		ret.rs = max(b.rs,b.sum+a.rs);
		ret.best = max(a.best,b.best);
		ret.best = max(a.rs+b.ls,ret.best);
		return ret;
	}
}tree[2][maxn<<1];
ll tag[maxn<<1];

inline void add(int a,int b) { nxt[++cnt] = side[a]; side[a] = cnt; toit[cnt] = b; }
inline void ins(int a,int b) { add(a,b); add(b,a); }

void decompose(int now,int tp)
{
	redfn[dfn[now] = ++timestamp] = now;
	top[now] = tp; int heavy = 0;
	for (int i = side[now];i;i = nxt[i])
		if (toit[i] != father[now]&&size[toit[i]] > size[heavy]) heavy = toit[i];
	if (!heavy) return; decompose(heavy,tp);
	for (int i = side[now];i;i = nxt[i])
		if (toit[i] != father[now]&&toit[i] != heavy)
			decompose(toit[i],toit[i]);
}
inline void dfs(int now)
{
	size[now] = 1;
	for (int i = side[now];i;i = nxt[i])
		if (toit[i] != father[now])
		{
			father[toit[i]] = now;
			dep[toit[i]] = dep[now]+1; dfs(toit[i]);
			size[now] += size[toit[i]];
		}
}

inline void build(int now,int l,int r)
{
	tag[now] = inf;
	if (l == r) { tree[0][now] = tree[1][now] = Node(w[redfn[l]]); return; }
	int mid = (l+r)>>1;
	build(now<<1,l,mid); build(now<<1|1,mid+1,r);
	tree[0][now] = tree[0][now<<1]+tree[0][now<<1|1];
	tree[1][now] = tree[1][now<<1|1]+tree[1][now<<1];
}

inline void pushdown(int now,int l,int r)
{
	if (l != r)
	{
		int mid = (l+r)>>1;
		tree[0][now<<1].set(tag[now],mid-l+1);
		tree[1][now<<1] = tree[0][now<<1];
		tree[0][now<<1|1].set(tag[now],r-mid);
		tree[1][now<<1|1] = tree[0][now<<1|1];
		tag[now<<1] = tag[now<<1|1] = tag[now];
	}
	tag[now] = inf;
}

inline void modify(int now,int l,int r,int ql,int qr,int x)
{
	if (tag[now] != inf) pushdown(now,l,r);
	if (l == ql&&r == qr)
	{
		tree[0][now].set(x,r-l+1);
		tree[1][now] = tree[0][now];
		tag[now] = x;
		return;
	}
	int mid = (l+r)>>1;
	if (qr <= mid) modify(now<<1,l,mid,ql,qr,x);
	else if (ql > mid) modify(now<<1|1,mid+1,r,ql,qr,x);
	else
	{
		modify(now<<1,l,mid,ql,mid,x);
		modify(now<<1|1,mid+1,r,mid+1,qr,x);
	}
	tree[0][now] = tree[0][now<<1]+tree[0][now<<1|1];
	tree[1][now] = tree[1][now<<1|1]+tree[1][now<<1];
}
inline Node query(int type,Node arr[],int now,int l,int r,int ql,int qr)
{
	if (tag[now] != inf) pushdown(now,l,r);
	if (l == ql&&r == qr) return arr[now];
	int mid = (l+r)>>1;
	if (qr <= mid) return query(type,arr,now<<1,l,mid,ql,qr);
	else if (ql > mid) return query(type,arr,now<<1|1,mid+1,r,ql,qr);
	else {
		if(type == 0)
			return query(type,arr,now<<1,l,mid,ql,mid)+query(type,arr,now<<1|1,mid+1,r,mid+1,qr);
		else
			return query(type,arr,now<<1|1,mid+1,r,mid+1,qr)+query(type,arr,now<<1,l,mid,ql,mid);
	}
}

inline void modify(int a,int b,int c)
{
	while (top[a] != top[b])
	{
		if (dep[top[a]] < dep[top[b]]) swap(a,b);
		modify(1,1,N,dfn[top[a]],dfn[a],c);
		a = father[top[a]];
	}
	if (dep[a] < dep[b]) swap(a,b);
	modify(1,1,N,dfn[b],dfn[a],c);	
}

inline int query(int a,int b)
{
	Node retl, retr;
	while(top[a] != top[b]) {
		if(dep[top[a]] > dep[top[b]]) {
			retl = retl+query(1,tree[1],1,1,N,dfn[top[a]],dfn[a]);
			a = father[top[a]];
		} else {
			retr = query(0,tree[0],1,1,N,dfn[top[b]],dfn[b]) + retr;
			b = father[top[b]];
		}
	}
	if(dep[a] > dep[b]) {
		retl = retl+query(1,tree[1],1,1,N,dfn[b],dfn[a]);
	} else {
		retr = query(0,tree[0],1,1,N,dfn[a],dfn[b])+retr;
	}
	return (retl + retr).best;
}

int main()
{
	// freopen("D.in","r",stdin);
	scanf("%d %d",&N,&Q);
	for (int i = 1;i <= N;++i) scanf("%d",w+i);
	for (int i = 1;i < N;++i)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		ins(a,b);
	}
	dfs(1);
	decompose(1,1);
	build(1,1,N);
	while (Q--)
	{
		int opt; scanf("%d",&opt);
		if (opt == 1)
		{
			int a,b,c;
			scanf("%d %d %d",&a,&b,&c);
			modify(a,b,c);
		}
		else
		{
			int a,b,c;
			scanf("%d %d %d",&a,&b,&c);
			printf("%d\n",query(a,b));
		}
	}
	return 0;
}

Measured memory_bytes: 72900