#include <bits/stdc++.h> //Andrei Alexandru a.k.a Sho
#define ll long long
#define double long double
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#define aint(a) (a).begin(), (a).end()
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define pi pair
#define rc(s) return cout<<s,0
#define endl '\n'
#define mod 1000000007
#define PI 3.14159265359
#define INF 1000000005
#define LINF 1000000000000000005ll
#define CODE_START ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
ll n,q,a[200005],depth[200005],c[200005],roof[200005],lvl[200005],decc[200005],tree[800005],sz[200005],sub[200005],indx;
vector<ll>g[200005];
vector<ll>path[100005];
void dfs(ll node,ll par){
ll check=1;
sub[node]=1;
ll heavy=-1;
for(auto it : g[node]){
if(it!=par){
check=0;
depth[it]=depth[node]+1;
dfs(it,node);
sub[node]+=sub[it];
if(heavy==-1){
heavy=it;
}else if(sub[it]>sub[heavy]){
heavy=it;
}
}
}
if(check){
c[node]=++indx;
sz[indx]++;
path[indx].pb(node);
return;
}
c[node]=c[heavy];
sz[c[node]]++;
path[c[node]].pb(node);
for(auto it : g[node]){
if(it==heavy||depth[it]<depth[node]){
continue;
}else {
roof[c[it]]=node;
lvl[c[it]]=depth[node];
}
}
}
void build(ll node,ll l,ll r,ll lant,ll decalaj){
if(l==r){
tree[node+decalaj]=a[path[lant][l-1]];
return;
}
ll mid=(l+r)/2;
build(2*node,l,mid,lant,decalaj);
build(2*node+1,mid+1,r,lant,decalaj);
tree[node+decalaj]=max(tree[2*node+decalaj],tree[2*node+1+decalaj]);
}
void update(ll node,ll l,ll r,ll pos,ll val,ll decalaj){
if(l==r){
tree[node+decalaj]=val;
return;
}
ll mid=(l+r)/2;
if(pos<=mid){
update(2*node,l,mid,pos,val,decalaj);
}else {
update(2*node+1,mid+1,r,pos,val,decalaj);
}
tree[node+decalaj]=max(tree[2*node+decalaj],tree[2*node+1+decalaj]);
}
ll query(ll node,ll l,ll r,ll st,ll dr,ll decalaj){
if(l>dr){
return 0;
}
if(r<st){
return 0;
}
if(st<=l&&r<=dr){
return tree[node+decalaj];
}
ll mid=(l+r)/2;
return max(query(2*node,l,mid,st,dr,decalaj),query(2*node+1,mid+1,r,st,dr,decalaj));
}
int32_t main(){
CODE_START;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
cin>>n>>q;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
}
for(ll i=1;i<n;i++)
{
ll l,r;
cin>>l>>r;
g[l].pb(r);
g[r].pb(l);
}
depth[1]=1;
dfs(1,0);
for(ll i=1;i<=indx;i++)
{
reverse(path[i].begin(),path[i].end());
}
for(ll i=1;i<=indx;i++)
{
if(i>1){
decc[i]=decc[i-1]+sz[i-1]*4;
}
build(1,1,sz[i],i,decc[i]);
}
while(q--){
ll type,x,y;
cin>>type>>x>>y;
if(type==0){
update(1,1,sz[c[x]],depth[x]-lvl[c[x]],y,decc[c[x]]);
}else {
ll ans=0;
while(true){
if(c[x]==c[y]){
if(depth[x]>depth[y]){
swap(x,y);
}
ans=max(ans,query(1,1,sz[c[x]],depth[x]-lvl[c[x]],depth[y]-lvl[c[y]],decc[c[x]]));
break;
}else {
if(lvl[c[x]]<lvl[c[y]]){
swap(x,y);
}
ans=max(ans,query(1,1,sz[c[x]],1,depth[x]-lvl[c[x]],decc[c[x]]));
x=roof[c[x]];
}
}
cout<<ans<<endl;
}
}
}