#include<cstdio>
#include<stack>
#include<utility>
#include<algorithm>

using namespace std;

typedef pair<int,int> P;

const long long inf=1ll<<40;

int m,head[200200],to[400400],nxt[400400];
bool heavy[400400];
int heavy_child[400400];
int weight[200200];
int N;

void edge_init(){
	for(int i=0;i<N;i++) head[i]=-1;
	m=0;
}

void add_edge(int u,int v){
	nxt[m]=head[u];to[m]=v;head[u]=m;m++;
	nxt[m]=head[v];to[m]=u;head[v]=m;m++;
}

int w[262144];
int seg_id[200200];

int sz[200200];
int top[200200];
int dep[200200];
int par[200200][20];
int pre[200200];
int rpre[200200];

int times[200200];

void dfs_(){
	stack<int> st;
	st.push(0);
	dep[0]=0;
	par[0][0]=-1;
	top[0]=0;
	int c=0;
	while(!st.empty()){
		int cur=st.top();
		st.pop();
		if(times[cur]==0){
			st.push(cur);
			rpre[c]=cur;
			pre[cur]=c++;
			for(int e=head[cur];e!=-1;e=nxt[e]){
				int v=to[e];
				if(times[v]==0){
					st.push(v);
					par[v][0]=cur;
					dep[v]=dep[cur]+1;
				}
			}
		}else if(times[cur]==1){
			sz[cur]=1;
			for(int e=head[cur];e!=-1;e=nxt[e]){
				int v=to[e];
				if(times[v]==2){
					sz[cur]+=sz[v];
				}
			}
		}
		times[cur]++;
	}
	for(int j=1;j<20;j++){
		for(int i=0;i<N;i++){
			if(par[i][j-1]==-1) par[i][j]=-1;
			else par[i][j]=par[par[i][j-1]][j-1];
		}
	}
}

P getLca(int u,int v){
	bool flipped=false;
	if(dep[u]>dep[v]){
		flipped=true;
		swap(u,v);
	}
	int d=dep[v]-dep[u];
	for(int i=0;i<20;i++){
		if((d>>i)&1){
			v=par[v][i];
		}
	}
	if(u==v) return P(v,v);
	for(int i=19;i>=0;i--){
		if(par[u][i]!=par[v][i]){
			u=par[u][i];
			v=par[v][i];
		}
	}
	if(!flipped) return P(par[u][0],u);
	else return P(par[v][0],v);
}

void decompose(){
	for(int v=0;v<N;v++){
		if(sz[v]==1) continue;
		int Ma=-1;
		int id=-1;
		for(int e=head[v];e!=-1;e=nxt[e]){
			int u=to[e];
			if(par[v][0]==u) continue;
			if(Ma<sz[u]){
				Ma=sz[u];
				id=e;
			}
		}
		heavy[id]=true;
		heavy[id^1]=true;
	}
	for(int v=0;v<N;v++){
		top[v]=-1;
	}
	for(int i=0;i<N;i++){
		int v=rpre[i];
		if(top[v]==-1){
			top[v]=v;
		}
		for(int e=head[v];e!=-1;e=nxt[e]){
			int u=to[e];
			if(u==par[v][0]) continue;
			if(heavy[e]){
				top[u]=top[v];
			}
		}
	}
	int c=0;
	for(int v=0;v<N;v++){
		heavy_child[v]=-1;
	}
	for(int u=0;u<N;u++){
		if(top[u]!=u) continue;
		int v=u;
		while(true){
//			printf("v=%d\n",v);
			seg_id[v]=c++;
			int ch=-1;
			for(int e=head[v];e!=-1;e=nxt[e]){
				int u=to[e];
				if(par[v][0]==u) continue;
				if(!heavy[e]) continue;
				ch=u;
				break;
			}
			heavy_child[v]=ch;
//			printf("ch=%d\n",ch);
			if(ch==-1) break;
			v=ch;
		}
	}
	for(int i=0;i<N;i++){
		w[seg_id[i]]=weight[i];
	}
}

struct Node{
	long long left,right,both,all;
	Node(){}
	Node(int val,int num){
		if(val>=0){
			left=val*num;
			right=val*num;
			both=val*num;
			all=val*num;
		}else{
			left=val;
			right=val;
			both=val*num;
			all=val;
		}
	}
	Node operator+(const Node &n){
		Node res;
		res.left=max(left,both+n.left);
		res.right=max(n.right,n.both+right);
		res.all=max(max(all,n.all),right+n.left);
		res.both=both+n.both;
		return res;
	}
	Node flip(){
		Node res=*this;
		swap(res.left,res.right);
		return res;
	}
};

struct Segtree{
	Node nodes[524288];
	bool all_same[524288];
	int val[524288];
	int num[524288];
	int N;
	void init(int N_,int *w){
		N=1;
		while(N<N_) N*=2;
		for(int i=N;i<N*2;i++){
			num[i]=1;
			nodes[i]=Node(w[i-N],1);
			all_same[i]=false;
		}
		for(int i=N-1;i>=1;i--){
			num[i]=num[i*2]+num[i*2+1];
			nodes[i]=nodes[i*2]+nodes[i*2+1];
			all_same[i]=false;
		}
	}
	void calc(int k){
		if(!all_same[k]) return;
		nodes[k]=Node(val[k],num[k]);
	}
	Node get(int l,int r,int k,int a,int b){
		calc(k);
		if(r<=a||b<=l) return Node();
		if(l<=a&&b<=r){
			return nodes[k];
		}
		if(all_same[k]){
			all_same[k*2]=true;
			val[k*2]=val[k];
			all_same[k*2+1]=true;
			val[k*2+1]=val[k];
			calc(k*2);
			calc(k*2+1);
		}
		int mid=(a+b)/2;
		Node le=get(l,r,k*2,a,mid);
		Node ri=get(l,r,k*2+1,mid,b);
		if(r<=mid) return le;
		else if(mid<=l) return ri;
		else return le+ri;
	}
	Node get(int l,int r){
		return get(l,r,1,0,N);
	}
	void update(int l,int r,int x,int k,int a,int b){
		if(l<=a&&b<=r){
			all_same[k]=true;
			val[k]=x;
			calc(k);
			return;
		}else if(r<=a||b<=l){
			return;
		}
		if(all_same[k]){
			all_same[k*2]=true;
			all_same[k*2+1]=true;
			val[k*2]=val[k];
			val[k*2+1]=val[k];
			calc(k*2);
			calc(k*2+1);
		}
		all_same[k]=false;
		update(l,r,x,k*2,a,(a+b)/2);
		update(l,r,x,k*2+1,(a+b)/2,b);
		nodes[k]=nodes[k*2]+nodes[k*2+1];
	}
	void update(int l,int r,int x){
//		printf("update [%d,%d)\n",l,r);
		update(l,r,x,1,0,N);
	}
};

Segtree seg;

Node path[100100];

int get_path(int v,int p,Node *res,bool rev){
//	printf("from %d to %d\n",v,p);
	int len=0;
//	int cnt=0;
	while(true){
//		cnt++;
//		if(cnt>10) break;
		int t=top[v];
//		printf("v=%d,t=%d ",v,t);
		if(dep[t]>=dep[p]){
			int le=seg_id[t];
			int ri=seg_id[v];
			Node n=seg.get(le,ri+1);
//			printf("[%d,%d]",le,ri);
			res[len]=n.flip();
			len++;
			if(t==p) break;
			v=par[t][0];
		}else{
			int le=seg_id[p];
			int ri=seg_id[v];
			Node n=seg.get(le,ri+1);
//			printf("[%d,%d]",le,ri);
			res[len]=n.flip();
			len++;
			break;
		}
	}
	if(rev){
//		printf("---reverse---\n");
		reverse(res,res+len);
		for(int i=0;i<len;i++){
			res[i]=res[i].flip();
		}
	}else{
//		printf("---dont reverse---\n");
	}
	return len;
}

void get_and_update_path(int v,int p,int x){
//	printf("get_and_update(%d,%d)\n",v,p);
	while(true){
		int t=top[v];
//		printf("v=%d,t=%d\n",v,t);
		if(dep[t]>=dep[p]){
			int le=seg_id[t];
			int ri=seg_id[v];
			seg.update(le,ri+1,x);
			if(t==p) break;
			v=par[t][0];
		}else{
			int le=seg_id[p];
			int ri=seg_id[v];
			seg.update(le,ri+1,x);
			break;
		}
	}
}

int solve(int u,int v){
	P p=getLca(u,v);
	int len=0;
	int w=p.second,lca=p.first;
	if(w==lca){
		if(u==w){
			len+=get_path(v,w,path,false);
		}else{
			len+=get_path(u,w,path,false);
		}
	}else{
		len+=get_path(u,w,path,false);
		len+=get_path(v,lca,path+len,true);
	}
	Node n=path[0];
	for(int i=1;i<len;i++){
		n=n+path[i];
	}
	return n.all;
}

void update(int u,int v,int x){
	P p=getLca(u,v);
	int w=p.second,lca=p.first;
	if(w==lca){
		if(u==w){
			get_and_update_path(v,w,x);
		}else{
			get_and_update_path(u,w,x);
		}
	}else{
		get_and_update_path(u,w,x);
		get_and_update_path(v,lca,x);
	}
}

int Q;

int main(){
	scanf("%d%d",&N,&Q);
	for(int i=0;i<N;i++) scanf("%d",weight+i);
	edge_init();
	for(int i=0;i<N-1;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		u--;v--;
		add_edge(u,v);
	}
	dfs_();
	decompose();
/*	for(int i=0;i<N;i++){
		printf("sz[%d]=%d\n",i,sz[i]);
	}
	for(int i=0;i<N;i++){
		printf("par[%d]=%d\n",i,par[i][0]);
	}
	for(int i=0;i<N;i++){
		printf("top[%d]=%d\n",i,top[i]);
	}
	for(int i=0;i<N;i++){
		printf("heavy_child[%d]=%d\n",i,heavy_child[i]);
	}
	for(int i=0;i<N;i++){
		printf("seg_id[%d]=%d\n",i,seg_id[i]);
	}*/
/*	for(int i=0;i<N;i++){
		printf("dep[%d]=%d\n",i,dep[i]);
	}*/
//	get_path(2,0,path,false);
//	get_path(4,3,path,false);
//	get_path(6,0,path,false);
//	get_path(6,5,path,false);
	seg.init(N,w);
/*	for(int i=0;i<N;i++){
		printf("w[%d]=%d\n",i,w[i]);
	}
	printf("seg.get(%d,%d)=%d\n",1,4,seg.get(1,4));
	printf("solve(1,3) = %d\n",solve(1,3));
	printf("solve(2,4) = %d\n",solve(2,4));*/
	for(int q=0;q<Q;q++){
		int type,u,v,x;
		scanf("%d%d%d%d",&type,&u,&v,&x);
		u--;v--;
		if(type==1){
			update(u,v,x);
		}else{
			int ans=solve(u,v);
			printf("%d\n",ans);
		}
	}
	return 0;
}

Measured memory_bytes: 52072