#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
vector<int> aint, lant, l_niv, niv, d_lant, a, p_lant, w;
vector<vector<int>> tabel, ll;
vector<bool> viz;
int cnt = 0;
void dfs(int nod,int pr){
int fr=1, mx=-1;
viz[nod] = true;
w[nod] = 1;
for(auto i : tabel[nod]){
if(i==pr) continue;
niv[i] = niv[nod]+1;
fr = 0;
dfs(i,nod);
w[nod] += w[i];
if(mx==-1 || w[i] > w[mx]) mx = i;
}
if(fr){
lant[nod] = ++cnt;
ll[cnt].push_back(nod);
} else {
ll[lant[mx]].push_back(nod);
lant[nod] = lant[mx];
for(auto i : tabel[nod]){
if(i==mx || i==pr) continue;
p_lant[lant[i]] = nod;
l_niv[lant[i]] = niv[nod];
}
}
}
void build(int nod,int st,int dr,int decalaj,int id){
if(st==dr){
aint[nod + decalaj] = a[ ll[id][st-1] ];
return;
}
int md=(st+dr)/2;
build(2*nod,st,md,decalaj,id);
build(2*nod+1,md+1,dr,decalaj,id);
aint[nod+decalaj] = max(aint[2*nod+decalaj], aint[2*nod+1+decalaj]);
}
void update(int nod,int st,int dr,int target,int v,int decalaj){
if(st==dr){
aint[nod+decalaj] = v;
return;
}
int md=(st+dr)/2;
if(target<=md) update(2*nod,st,md,target,v,decalaj);
else update(2*nod+1,md+1,dr,target,v,decalaj);
aint[nod+decalaj] = max(aint[2*nod+decalaj], aint[2*nod+1+decalaj]);
}
int qeu(int nod,int st,int dr,int l,int r,int decalaj){
if(st>r || dr<l) return INT_MIN;
if(l<=st && dr<=r) return aint[nod+decalaj];
int md=(st+dr)/2;
return max(
qeu(2*nod,st,md,l,r,decalaj),
qeu(2*nod+1,md+1,dr,l,r,decalaj)
);
}
void bbuild(){
niv[1]=1;
dfs(1,0);
for(int i=1;i<=cnt;i++){
reverse(ll[i].begin(), ll[i].end());
if(i>1)
d_lant[i] = d_lant[i-1] + int(ll[i-1].size())*4;
build(1,1,int(ll[i].size()), d_lant[i], i);
}
}
void raspunde(){
int t,x,y;
fin >> t >> x >> y;
if(t==0){
update(1, 1, int(ll[lant[x]].size()),
niv[x] - l_niv[lant[x]], y,
d_lant[lant[x]]);
} else {
int rez = INT_MIN;
while(true){
if(lant[x]==lant[y]){
if(niv[x]>niv[y]) swap(x,y);
rez = max(rez,
qeu(1,1,int(ll[lant[x]].size()),
niv[x]-l_niv[lant[x]],
niv[y]-l_niv[lant[y]],
d_lant[lant[x]]));
break;
}
if(l_niv[lant[x]] < l_niv[lant[y]])
swap(x,y);
rez = max(rez,
qeu(1,1,int(ll[lant[x]].size()),
1,
niv[x]-l_niv[lant[x]],
d_lant[lant[x]]));
x = p_lant[lant[x]];
}
fout << rez << "\n";
}
}
int main(){
int N, M;
fin >> N >> M;
a.resize(N+1);
tabel.assign(N+1,{});
viz.assign(N+1,false);
w.assign(N+1,0);
lant.assign(N+1,0);
niv.assign(N+1,0);
l_niv.assign(N+1,0);
p_lant.assign(N+1,0);
d_lant.assign(N+1,0);
ll.assign(N+1,{});
aint.assign(4*N + 5, 0);
for(int i=1;i<=N;i++)
fin >> a[i];
for(int i=1,u,v;i<N;i++){
fin >> u >> v;
tabel[u].push_back(v);
tabel[v].push_back(u);
}
bbuild();
for(int i=0;i<M;i++)
raspunde();
return 0;
}