#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<list>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<string>
#define sgn(v) (abs((v))<eps?0:((v)<0?-1:1))
#define sqr(v) ((v)*(v))
#define mb make_pair
#define debug 0
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,ll> pil;
typedef pair<ll,int> pli;
typedef pair<ll,ll> pll;
const double eps=1e-9;
const double pi=acos(-1);
const int maxn=2e5+100;
struct Edge
{
	int v,next;
}edge[maxn*2];
int ne,head[maxn];
void add(int u,int v)
{
	edge[ne].v=v;
	edge[ne].next=head[u];
	head[u]=ne++;
}
int sz[maxn],hv[maxn],dep[maxn],fa[maxn],anc[maxn],id[maxn],idx;
int w[maxn],who[maxn];
void pre_dfs(int u,int pre)
{
	sz[u]=1;hv[u]=0;dep[u]=dep[pre]+1;fa[u]=pre;
	int i,v;
	for(i=head[u];i!=-1;i=edge[i].next)
	{
		v=edge[i].v;
		if(v==pre)continue;
		pre_dfs(v,u);
		sz[u]+=sz[v];
		if(sz[hv[u]]<sz[v])hv[u]=v;
	}
}
void pre_build(int u,int last)
{
	anc[u]=last;id[u]=++idx;who[idx]=u;
	if(hv[u])pre_build(hv[u],last);
	int i,v;
	for(i=head[u];i!=-1;i=edge[i].next)
	{
		v=edge[i].v;
		if(v==fa[u]||v==hv[u])continue;
		pre_build(v,v);
	}
}
int max(int a,int b,int c)
{
	a=max(a,b);
	a=max(a,c);
	return a;
}
struct Node
{
	int sum,lmax,rmax,mmax;
	Node(){}
	Node(int w,int len)
	{
		if(w>=0)
			sum=lmax=rmax=mmax=w*len;
		else
		{
			sum=w*len;
			lmax=rmax=mmax=w;
		}
	}
	Node operator +(const Node &p)const
	{
		Node res;
		res.sum=sum+p.sum;
		res.lmax=max(lmax,sum+p.lmax);
		res.rmax=max(p.rmax,p.sum+rmax);
		res.mmax=max(mmax,p.mmax,rmax+p.lmax);
		return res;
	}
};
#define lch (id<<1)
#define rch (id<<1|1)
int f,ans,pre;
vector<Node> vl,vr;
const int mliv=-20000;
struct Segment
{
	Node tr[maxn<<2];
	int lazy[maxn<<2];
	void build(int id,int l,int r)
	{
		lazy[id]=mliv;
		if(l==r)
			tr[id]=Node(w[who[l]],1);
		else 
		{
			int mid=(l+r)/2;
			build(lch,l,mid);
			build(rch,mid+1,r);
			tr[id]=tr[lch]+tr[rch];
		}
	}
	void push_down(int id,int l,int r)
	{
		int mid=l+r>>1;
		int c=lazy[id];
		tr[lch]=Node(c,mid-l+1);
		lazy[lch]=c;
		tr[rch]=Node(c,r-mid);
		lazy[rch]=c;
		lazy[id]=mliv;
	}
	void update(int id,int l,int r,int L,int R,int c)
	{
		if(L<=l&&r<=R)
		{
			tr[id]=Node(c,r-l+1);
			lazy[id]=c;
		}
		else
		{
			int mid=l+r>>1;
			if(lazy[id]!=mliv)push_down(id,l,r);
			if(L<=mid)update(lch,l,mid,L,R,c);
			if(R>mid)update(rch,mid+1,r,L,R,c);
			tr[id]=tr[lch]+tr[rch];
		}
	}
	Node query(int id,int l,int r,int L,int R)
	{
		if(L<=l&&r<=R)
		{
			f=max(tr[id].mmax,pre+tr[id].rmax);
			pre=max(tr[id].lmax,pre+tr[id].sum);
			ans=max(f,ans);
			ans=max(pre,ans);
			return tr[id];
		}
		else
		{
			int mid=l+r>>1;
			if(lazy[id]!=mliv)push_down(id,l,r);
			tr[id]=tr[lch]+tr[rch];
			if(L>mid)return query(rch,mid+1,r,L,R);
			else if(R<=mid)return query(lch,l,mid,L,R);
			else return query(lch,l,mid,L,R)+query(rch,mid+1,r,L,R);
		}
	}
}Tr;
void modify(int x,int y,int c)
{
	int fx=anc[x],fy=anc[y];
	while(fx!=fy)
	{
		if(dep[fx]<dep[fy])
			swap(fx,fy),swap(x,y);
		Tr.update(1,1,idx,id[fx],id[x],c);
		x=fa[fx];fx=anc[x];
	}
	if(dep[x]<dep[y])swap(x,y);
	Tr.update(1,1,idx,id[y],id[x],c);
}
const int INF=2e9+100;
int query(int x,int y)
{
	ans=-INF;
	int fx=anc[x],fy=anc[y],i;
	vl.clear();vr.clear();
	while(fx!=fy)
	{
		if(dep[fx]<dep[fy])// fy
		{
			//cout <<"r:"<<y<<" "<<fy<<endl;
			f=pre=0;
			vr.push_back(Tr.query(1,1,idx,id[fy],id[y]));
			y=fa[fy];fy=anc[y];
		}
		else
		{
			//cout <<"l:"<<x<<" "<<fx<<endl;
			f=pre=0;
			vl.push_back(Tr.query(1,1,idx,id[fx],id[x]));
			x=fa[fx];fx=anc[x];
		}
	}
	//cout <<"l:"<<y<<" "<<x<<endl;
	if(dep[x]<dep[y])
	{
		f=pre=0;
		vr.push_back(Tr.query(1,1,idx,id[x],id[y]));
	}
	else
	{
		f=pre=0;
		vl.push_back(Tr.query(1,1,idx,id[y],id[x]));
	}
	f=pre=0;
	for(i=0;i<vl.size();++i)
	{
		//cout <<"l:"<<vl[i].sum<<" "<<vl[i].lmax<<" "<<vl[i].rmax<<" "<<vl[i].mmax<<endl;
		f=max(vl[i].mmax,pre+vl[i].rmax);
		pre=max(vl[i].lmax,pre+vl[i].sum);
		ans=max(f,ans);
		ans=max(pre,ans);
	}
	for(i=vr.size()-1;i>=0;--i)
	{
		//cout <<"r:"<<vr[i].sum<<" "<<vr[i].lmax<<" "<<vr[i].rmax<<" "<<vr[i].mmax<<endl;
		f=max(vr[i].mmax,pre+vr[i].lmax);
		pre=max(vr[i].rmax,pre+vr[i].sum);
		ans=max(f,ans);
		ans=max(pre,ans);
	}
	return ans;
}
int main()
{
	int i,n,q;
	int u,v,a,b,c,t;
	scanf("%d%d",&n,&q);
	ne=0;
	memset(head,-1,sizeof(head));
	for(i=1;i<=n;++i)scanf("%d",&w[i]);
	for(i=1;i<n;++i)
	{
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	//cout <<ne<<endl;
	//cout <<"dfs"<<endl;
	pre_dfs(n/2+1,0);
	idx=0;
	//cout <<"dfs"<<endl;
	pre_build(n/2+1,n/2+1);
	//for(i=1;i<=n;++i)cout <<fa[i]<<" ";cout <<endl;
	//for(i=1;i<=n;++i)cout <<hv[i]<<" ";cout <<endl;
	//for(i=1;i<=n;++i)cout <<anc[i]<<" ";cout <<endl;
	Tr.build(1,1,idx);
	//cout <<"build"<<endl;
	for(i=0;i<q;++i)
	{
		scanf("%d%d%d%d",&t,&a,&b,&c);
		if(t==1)
			modify(a,b,c);
		else
			printf("%d\n",query(a,b));
	}
	return 0;
}

Measured memory_bytes: 32572