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

typedef long long ll;
typedef tuple<ll,ll,ll,ll> state;
const ll INF=1LL<<60;

inline state vmerge(state l,state r){
	state ret;
	get<0>(ret)=max({get<0>(l),get<0>(r),get<3>(l)+get<2>(r)});
	get<1>(ret)=get<1>(l)+get<1>(r);
	get<2>(ret)=max(get<2>(l),get<1>(l)+get<2>(r));
	get<3>(ret)=max(get<3>(r),get<1>(r)+get<3>(l));
	return ret;
}

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],sz[nmax];
SegmentTree<ll>* seg[nmax];

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

tuple<int,int> lca(int &a,int &b){
	if(depth[a]>depth[b]) swap(a,b);
	int u=a,v=b;
	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,u);
	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]);
}

vector<int> chain[nmax];
int idx[nmax],pos[nmax];

int hld(int v,int p,int &id){
    idx[v]=id,pos[v]=chain[id].size();
    chain[id].push_back(v);
    int cmax=-1,u=-1;
    for(auto &v2:tree[v]){
    	if(v2==p) continue;
    	if(cmax<sz[v2]) cmax=sz[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 v, int root, int cost){
	while(1){
		int u=chain[idx[v]][0];
		if(depth[u]<=depth[root]) u=root;
		seg[idx[v]]->update(pos[u],pos[v]+1, cost);
		if(u==root) break;
		v=parent[u][0];
	}
	return;
}

state calc(int v,int root){
	state ret=make_tuple(-INF,0,-INF,-INF);
	while(1){
		int u=chain[idx[v]][0];
		if(depth[u]<=depth[root]) u=root;
		state cur=seg[idx[v]]->query(pos[u],pos[v]+1);
		ret=vmerge(cur,ret);
		if(u==root) break;
		v=parent[u][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);
	}
	int k=0;
	dfs(0,-1,0);
	int m=hld(0,-1,k);

	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,m) seg[i]=new SegmentTree<ll>(chain[i].size(),-INF);
	rep(i,n) seg[idx[i]]->update(pos[i],pos[i]+1,w[i]);

	rep(loop,q){
		int t,a,b,c;
		cin >> t >> a >> b >> c;
		a--,b--;
		int u,v;
		tie(u,v)=lca(a,b);
		if(t==1){
			if(v==a)
				fix(b,a,c);
			else
				fix(a,u,c),fix(b,v,c);
		}else{
			if(v==a){
				state cur=calc(b,a);
				cout << get<0>(cur) << endl;
			}else{
				state left=calc(a,u),right=calc(b,v);
				swap(get<2>(left),get<3>(left));
				cout << get<0>(vmerge(left,right)) << 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: 82460