#include  <bits/stdc++.h>
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
using namespace std;

typedef long long ll;
typedef tuple<int,int> tii;
typedef tuple<ll,ll,ll,ll> state;

const ll INF=1LL<<60;

inline state vmerge(state l,state r){
	ll ans,all,left,right;
	ll lans,lall,lleft,lright;
	tie(lans,lall,lleft,lright)=l;
	ll rans,rall,rleft,rright;
	tie(rans,rall,rleft,rright)=r;
	ans=max({ lans,rans,lright+rleft});
	all=lall+rall;
	left=max(lleft,lall+rleft);
	right=max(rright,rall+lright);
	return make_tuple(ans,all,left,right);
}

template <typename T> class SegmentTree{
	public:
		int n;
		SegmentTree(int size,T o): out(o){
			for(n=1;n<size;n<<=1);
			data=vector<state>(2*n,make_tuple(out,0,out,out));
			lazy=vector<T>(2*n,out);
		}

		void update(int a,int b,T x,int k,int l,int r){
			if(r<=a || b<=l) return;
			if(a<=l&&r<=b){
				lazy[k]=x;
				T ans=max(x,x*(r-l)),all=x*(r-l);
				T left=ans,right=ans;
				data[k]=make_tuple(ans,all,left,right);
				return ;
			}
			lazy_evaluate(k,l,r);
			update(a,b,x,k*2+1,l,(l+r)/2);
			update(a,b,x,k*2+2,(l+r)/2,r);
			data[k]=vmerge(data[k*2+1],data[k*2+2]);
		}

		void update(int a,int b,T x){return update(a,b,x,0,0,n);}

		state query(int a,int b,int k,int l,int r){
			if(r<=a||b<=l) return make_tuple(-INF,0,-INF,-INF);
			if(a<=l&&r<=b) return data[k];
			lazy_evaluate(k,l,r);
			state vl = query(a,b,k*2+1,l,(l+r)/2);
			state vr = query(a,b,k*2+2,(l+r)/2,r);
			return vmerge(vl,vr);
		}

		state query(int a,int b) {return query(a,b,0,0,n);}

	private:
		vector<state> data;
		vector<T> lazy;
		const T out;

		inline void lazy_evaluate(int k,int l,int r){
			if(lazy[k]==out) return;
			T x=lazy[k];
			update(l,(l+r)/2,x,k*2+1,l,(l+r)/2);
			update((l+r)/2,r,x,k*2+2,(l+r)/2,r);
			lazy[k]=out;
		}
};

const int nmax=200010;
vector<int> tree[nmax];
int depth[nmax],parent[nmax][20],subsize[nmax];
SegmentTree<ll>* seg[nmax];

int dfs(int v,int p,int d){
	depth[v]=d;
	parent[v][0]=p;
	subsize[v]=1;
	for(auto &v2:tree[v]){
		if(v2==p) continue;
		subsize[v]+=dfs(v2,v,d+1);
	}
	return subsize[v];
}

tii lca(int u,int v){
	for(int i=19;i>=0;--i) if((depth[v]-depth[u])>>i&1) v=parent[v][i];
	if(u==v) return make_tuple(u,v);
	for(int i=19;i>=0;--i){
		if(parent[u][i]!=parent[v][i]){
			u=parent[u][i];
			v=parent[v][i];
		}
	}
	return make_tuple(u,parent[u][0]);
}

struct {int head,pos,index,size;}chain[nmax];

int hld(int v,int p,int &id) {
    if(chain[id].head == -1) chain[id].head=v;
    chain[v].index=id;
   	chain[v].pos=chain[id].size;
    chain[id].size++;

    int cmax=-1,u=-1;
    for(auto &v2:tree[v]){
    	if(v2==p) continue;
    	if(cmax<subsize[v2]) cmax=subsize[v2],u=v2;
    }

    if(u>=0) hld(u,v,id);

    for(auto &v2:tree[v]){
    	if(v2==p||v2==u) continue;
    	hld(v2,v,++id);
    }
    return id+1;
}

void fix(int a, int b, int c){
	while(1){
		int v=chain[chain[a].index].head;
		if(depth[v]<=depth[b]) v=b;
		seg[chain[a].index]->update(chain[v].pos,chain[a].pos+1, c);
		if(v==b) break;
		a=parent[v][0];
	}
	return;
}

state calc(int a,int b){
	state ret=make_tuple(-INF,0,-INF,-INF);
	while(1){
		int v=chain[chain[a].index].head;
		if(depth[v]<=depth[b]) v=b;
		state cur=seg[chain[a].index]->query(chain[v].pos,chain[a].pos+1);
		ret=vmerge(cur,ret);
		if(v==b) break;
		a=parent[v][0];
	}
	return ret;
}

int n,q,w[nmax];

void run(void){
	cin >> n >> q;
	rep(i,n) cin >> w[i];
	rep(i,n-1){
		int a,b;
		cin >> a >> b;
		tree[a-1].push_back(b-1);
		tree[b-1].push_back(a-1);
	}
	rep(i,n) chain[i].head=-1,chain[i].index=chain[i].pos=chain[i].size=0;
	int chain_num=0;
	dfs(0,-1,0);
	int m=hld(0,-1,chain_num);

	rep(d,19)rep(i,n){
		if(parent[i][d]==-1)
			parent[i][d+1]=-1;
		else
			parent[i][d+1]=parent[parent[i][d]][d];
	}

	/*
	rep(i,n){
		cerr << "vertex: " << i << endl;
		rep(d,3) cerr << parent[i][d] << endl;
	}
	*/
	rep(i,m) seg[i]=new SegmentTree<ll>(chain[i].size,-INF);
	rep(i,n) seg[chain[i].index]->update(chain[i].pos,chain[i].pos+1,w[i]);

	rep(loop,q){
		int t,a,b,c;
		cin >> t >> a >> b >> c;
		a--,b--;
		if(depth[a]>depth[b]) swap(a,b);
		int u,v;
		tie(u,v)=lca(a,b);
		if(t==1){
			fix(a,v,c),fix(b,v,c);
		}else{
			ll ans;
			if(v==a){
				state cur=calc(b,a);
				ans=get<0>(cur);
			}else{
				//cerr << a << " " << u << endl;
				//cerr << b << " " << v << endl;

				// cerr << parent[a][0] << " " << parent[a][1] << endl;
				state left=calc(a,u),right=calc(b,v);
				//cerr << get<2>(left) << " " << get<3>(left) << endl;
				swap(get<2>(left),get<3>(left));
				ans=get<0>(vmerge(left,right));
				// cerr << get<2>(left) << " " << get<3>(left) << endl;
			}
			cout << ans << endl;
		}
	}
	return;
}

long long esp_org, esp_new; //??????????????????
int main(){
	const int size = 128*1024*1024;
	void *p = malloc(size);
	esp_new = (long long)p + size - 1;


	__asm__("mov %%rsp, %0" : "=r"(esp_org) : : );
	__asm__("mov %0, %%rsp" : : "r"(esp_new) : );

	run();

	__asm__("mov %0, %%rsp" : : "r"(esp_org) : );
	free(p);
	return 0;
}

Measured memory_bytes: 73088