#include <bits/stdc++.h>
#define ll long long
#define all(a) (a).begin(), (a).end()
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define sz() size()
#define fr first
#define sc second
#define pb push_back
#define er erase
#define in insert
#define pi pair<int,int>
#define pii pair<pair<int,int>,int>
#define mp make_pair
#define int long long
#define rc(s) return cout<<s,0
#define rcc(s) cout<<s,exit(0)
using namespace std;
const int mod=1e9+7;
const int modp=1999999973;
int n,m,val[100005],niv[100005],sub[100005],nrLight,pathid[100005];
int pathsize[100005],tata[100005],pathlvl[100005],tree[400005],pathdecalaj[100005];
bitset<100005>viz;
vector<int>path[100005],nod[100005];
void DFS(int s){
viz[s]=1;
sub[s]=1;
int frunza=1,heavyN=-1;
for(auto it:nod[s]){
if(viz[it]==1) continue;
niv[it] = niv[s]+1;
frunza = 0;
DFS(it);
sub[s]+=sub[it];
if(heavyN==-1) heavyN=it;
else{
if(sub[it]>sub[heavyN]) heavyN=it;
}
}
if(frunza==1){
++nrLight;
pathid[s]=nrLight;
pathsize[s]=1;
path[nrLight].push_back(s);
return;
}
pathid[s]=pathid[heavyN];
pathsize[pathid[s]]++;
path[pathid[s]].push_back(s);
for(auto it:nod[s]){
if(it==heavyN || niv[it]<niv[s]) continue;
tata[pathid[it]]=s;
pathlvl[pathid[it]]=niv[s];
}
return;
}
void build(int l,int r,int decalaj,int lant,int nod){
if(l==r){
tree[nod+decalaj]=val[path[lant][l-1]];
return;
}
else{
int mid=l+(r-l)/2;
build(l,mid,decalaj,lant,2*nod);
build(mid+1,r,decalaj,lant,2*nod+1);
tree[nod+decalaj]=max(tree[2*nod+decalaj],tree[2*nod+1+decalaj]);
return;
}
}
void create_paths(){
niv[1]=1;
DFS(1);
for(int i=1;i<=nrLight;i++){
reverse(all(path[i]));
if(i>1){
pathdecalaj[i]=pathdecalaj[i-1]+4*pathsize[i-1];
}
build(1,pathsize[i],pathdecalaj[i],i,1);
}
}
void update(int l,int r,int val,int poz,int decalaj,int nod){
if(left==right){
tree[nod+decalaj]=val;
return ;
}
int mid=l+(r-l)/2;
if(poz<=mid) update(l,mid,val,poz,decalaj,2*nod);
else update(mid+1,r,val,poz,decalaj,2*nod+1);
tree[nod+decalaj]=max(tree[2*nod+decalaj],tree[2*nod+1+decalaj]);
}
int query(int l,int r,int le,int re,int decalaj,int nod){
if(le>r || re<l) return 0;
else if(l>=le && r<=re){
return tree[nod+decalaj];
}
int mid=l+(r-l)/2;
return max(query(l,mid,le,re,decalaj,2*nod),query(mid+1,r,le,re,decalaj,2*nod+1));
}
int32_t main(){
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
ios_base::sync_with_stdio(false);cin.tie(0);cerr.tie(0);cout.tie(0);
srand(chrono::steady_clock::now().time_since_epoch().count());
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> val[i];
}
for(int i=1;i<n;i++){
int x,y;
cin >> x >> y;
nod[x].push_back(y);
nod[y].push_back(x);
}
cout << "CHECK" << '\n';
create_paths();
for(int i=1;i<=m;i++){
int t,x,y;
cin >> t >> x >> y;
if(t==0){
update(1,pathsize[pathid[x]],y,niv[x]-pathlvl[tata[pathid[x]]],pathdecalaj[pathid[x]],1);
}
else{
int ans=0;
while(true==true){
if(pathid[x]==pathid[y]){
if(niv[x]>niv[y]) swap(x,y);
ans=max(ans,query(1,pathsize[pathid[x]],niv[x]-pathlvl[pathid[x]],niv[y]-pathlvl[pathid[y]],pathdecalaj[pathid[x]],1));
break;
}
if(pathlvl[pathid[x]]<pathlvl[pathid[y]]) swap(x,y);
ans=max(ans,query(1,pathsize[pathid[x]],1,niv[x]-pathlvl[pathid[x]],pathdecalaj[pathid[x]],1));
x=max(x,tata[pathid[x]]);
}
cout << ans << '\n';
}
}
}