#include <bits/stdc++.h>
using namespace std;

#define repi(i,a,b) for(int i=int(a);i<int(b);i++)
#define peri(i,a,b) for(int i=int(b);i-->int(a);)
#define rep(i,n) repi(i,0,n)
#define per(i,n) peri(i,0,n)
#define all(c) begin(c),end(c)
#define mp make_pair
#define mt make_tuple

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;

constexpr ll INF=1e18;

vvi HeavyLightDecomposition(const vvi& g,int root=0)
{
	int n=g.size();
	vi sizes(n);
	for(stack<pii> st(deque<pii>(1,mp(-1,root)));st.size();){
		int p,u; tie(p,u)=st.top();
		if(sizes[u]==0){
			sizes[u]++;
			for(int v:g[u]) if(v!=p)
				st.emplace(u,v);
		}
		else{
			st.pop();
			for(int v:g[u]) if(v!=p)
				sizes[u]+=sizes[v];
		}
	}
	vvi paths(1);
	for(stack<tuple<int,int,int>> st(deque<tuple<int,int,int>>(1,mt(-1,root,0)));st.size();){
		int p,u,i; tie(p,u,i)=st.top(); st.pop();
		paths[i].push_back(u);
		for(int v:g[u]) if(v!=p){
			if(sizes[v]*2>=sizes[u])
				st.emplace(u,v,i);
			else{
				paths.push_back(vi());
				st.emplace(u,v,paths.size()-1);
			}
		}
	}
	return paths;
}

struct LCA{
	vi ds;
	vvi ps;
	LCA(const vvi& g,int root=0):ds(g.size()),ps(32-__builtin_clz(g.size()),vi(g.size(),-1)){
		for(stack<pii> st(deque<pii>(1,mp(-1,root)));st.size();){
			int p,u; tie(p,u)=st.top(); st.pop();
			for(int v:g[u]) if(v!=p){
				ds[v]=ds[u]+1;
				ps[0][v]=u;
				st.emplace(u,v);
			}
		}
		rep(i,ps.size()-1) rep(j,ps[i].size())
			ps[i+1][j]=ps[i][j]==-1?-1:ps[i][ps[i][j]];
	}
	int Find(int u,int v){
		if(ds[u]>ds[v]) swap(u,v);
		rep(i,ps.size())
			if((ds[v]-ds[u])>>i&1)
				v=ps[i][v];
		if(u==v) return u;
		per(i,ps.size())
			if(ps[i][u]!=ps[i][v])
				u=ps[i][u],v=ps[i][v];
		return ps[0][u];
	}
};

int NextPow2(int x)
{
	x--;
	for(int i=1;i<32;i*=2) x|=x>>i;
	return x+1;
}

struct SegmentTree{
	int size;
	vl sums,maxs,lmaxs,rmaxs,props;
	vi flags;
	SegmentTree(int n)
		:size(NextPow2(n)),sums(size*2),maxs(size*2,-INF),
		 lmaxs(size*2,-INF),rmaxs(size*2,-INF),props(size*2),flags(size*2){}
	void Update(int ql,int qr,ll x){Update(ql,qr,x,1,0,size);}
	tuple<ll,ll,ll,ll> Query(int ql,int qr){return Query(ql,qr,1,0,size);}
	
	void Propagate(int i){
		if(!flags[i]) return;
		flags[i]=0;
		if(i<size){
			props[i*2]=props[i*2+1]=props[i];
			flags[i*2]=flags[i*2+1]=1;
			rep(j,2){
				props[i*2+j]=props[i];
				flags[i*2+j]=1;
				sums[i*2+j]=sums[i]/2;
				maxs[i*2+j]=lmaxs[i*2+j]=rmaxs[i*2+j]=max(sums[i*2+j],props[i]);
			}
		}
	}
	void Update(int ql,int qr,ll x,int i,int l,int r){
		if(qr<=l || r<=ql) return;
		if(ql<=l && r<=qr){
			props[i]=x;
			flags[i]=1;
			sums[i]=x*(r-l);
			maxs[i]=lmaxs[i]=rmaxs[i]=max(sums[i],x);
			return;
		}
		Propagate(i);
		Update(ql,qr,x,i*2,l,(l+r)/2);
		Update(ql,qr,x,i*2+1,(l+r)/2,r);
		sums[i]=sums[i*2]+sums[i*2+1];
		maxs[i]=max({maxs[i*2],maxs[i*2+1],rmaxs[i*2]+lmaxs[i*2+1]});
		lmaxs[i]=max(lmaxs[i*2],sums[i*2]+lmaxs[i*2+1]);
		rmaxs[i]=max(rmaxs[i*2+1],rmaxs[i*2]+sums[i*2+1]);
	}
	tuple<ll,ll,ll,ll> Query(int ql,int qr,int i,int l,int r){
		if(qr<=l || r<=ql) return mt(0,-INF,-INF,-INF);
		if(ql<=l && r<=qr) return mt(sums[i],maxs[i],lmaxs[i],rmaxs[i]);
		Propagate(i);
		ll s1,m1,l1,r1; tie(s1,m1,l1,r1)=Query(ql,qr,i*2,l,(l+r)/2);
		ll s2,m2,l2,r2; tie(s2,m2,l2,r2)=Query(ql,qr,i*2+1,(l+r)/2,r);
		return mt(s1+s2,max({m1,m2,r1+l2}),max(l1,s1+l2),max(r2,r1+s2));
	}
};

int main()
{
	for(int n,q;~scanf("%d%d",&n,&q) && n|q;){
		vi ws(n);
		rep(i,n) scanf("%d",&ws[i]);
		vvi g(n);
		rep(i,n-1){
			int u,v; scanf("%d%d",&u,&v); u--,v--;
			g[u].push_back(v);
			g[v].push_back(u);
		}
		
		LCA lca(g);
		vvi paths=HeavyLightDecomposition(g);
		vi is(n),js(n);
		rep(i,paths.size()) rep(j,paths[i].size())
			is[paths[i][j]]=i,js[paths[i][j]]=j;
		
		vi parents(n,-1);
		{
			queue<int> q; q.push(0);
			while(q.size()){
				int u=q.front(); q.pop();
				for(int v:g[u]) if(v!=parents[u]){
					parents[v]=u;
					q.push(v);
				}
			}
		}
		
		vector<SegmentTree> sts;
		for(const auto& path:paths){
			int size=path.size();
			SegmentTree st(size);
			rep(i,size) st.Update(i,i+1,ws[path[i]]);
			sts.push_back(st);
		}
		
		rep(_,q){
			int t,u,v,x; scanf("%d%d%d%d",&t,&u,&v,&x); u--,v--;
			int a=lca.Find(u,v);
			if(t==1){
				for(;;){
					int left=is[u]==is[a]?js[a]:0;
					sts[is[u]].Update(left,js[u]+1,x);
					if(is[u]==is[a]) break;
					else u=parents[paths[is[u]][0]];
				}
				for(;;){
					int left=is[v]==is[a]?js[a]+1:0;
					sts[is[v]].Update(left,js[v]+1,x);
					if(is[v]==is[a]) break;
					else v=parents[paths[is[v]][0]];
				}
			}
			else{
				ll m1=-INF,l1=-INF;
				for(;;){
					int left=is[u]==is[a]?js[a]:0;
					ll s,m,l,r; tie(s,m,l,r)=sts[is[u]].Query(left,js[u]+1);
					tie(m1,l1)=mt(max({m,m1,r+l1}),max(l,s+l1));
					if(is[u]==is[a]) break;
					else u=parents[paths[is[u]][0]];
				}
				ll m2=-INF,l2=-INF;
				for(;;){
					int left=is[v]==is[a]?js[a]+1:0;
					ll s,m,l,r; tie(s,m,l,r)=sts[is[v]].Query(left,js[v]+1);
					tie(m2,l2)=mt(max({m,m2,r+l2}),max(l,s+l2));
					if(is[v]==is[a]) break;
					else v=parents[paths[is[v]][0]];
				}
				printf("%d\n",int(max({m1,m2,l1+l2})));
			}
		}
	}
}

Measured memory_bytes: 109616