#include <iostream>
#include <fstream>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
#define LE 160666
#include <vector>
vector<int> H[LE];
#define pb push_back
int n,nrq,i;
bool viz[LE];
int level[LE],lant_ind[LE],lant_pos[LE],lant_up[LE];
int st[LE*3];
vector<int> Arb[LE];
int father[LE],fap[LE*3];
int rmq[20][LE],k,Arb_sum[LE],val[LE];
int mpow[LE],nr_lant,grad[LE];
void dfs(int nod,int lev) {
viz[nod]=true;
level[nod]=lev;
int N=H[nod].size(),i;
fap[nod]=++k;
st[k]=nod;
Arb_sum[nod]=1;
for(i=0; i<N; ++i)
if (viz[H[nod][i]]==false) {
dfs(H[nod][i],lev+1);
st[++k]=nod;
Arb_sum[nod]+=Arb_sum[H[nod][i]];
father[H[nod][i]]=nod;
}
}
int get_lca(int nod1,int nod2) {
int x1=fap[nod1],x2=fap[nod2];
if (x1>x2) swap(x1,x2);
int D=x2-x1+1;
int P=mpow[D];
if (level[rmq[P][x1]]<level[rmq[P][x2-(1<<P)+1]])
return rmq[P][x1];
else return rmq[P][x2-(1<<P)+1];
}
void heavy_path(int nod) {
viz[nod]=true;
int N=H[nod].size(),i;
int max_nodes=0,node_unite;
for(i=0; i<N; ++i)
if (viz[H[nod][i]]==false) {
heavy_path(H[nod][i]);
if (Arb_sum[H[nod][i]]>max_nodes) {
max_nodes=Arb_sum[H[nod][i]];
node_unite=H[nod][i];
}
}
if (max_nodes==0) {
++nr_lant;
lant_ind[nod]=nr_lant;
lant_pos[nod]=1;
grad[nr_lant]=1;
} else {
++grad[lant_ind[node_unite]];
lant_ind[nod]=lant_ind[node_unite];
lant_pos[nod]=grad[lant_ind[node_unite]];
}
}
void update_arb(int Vnod,int i_arb,int i_pos,int st,int dr,int nod) {
int mij=(st+dr)/2;
if (st==dr) {
Arb[i_arb][nod]=Vnod;
return;
}
if (i_pos<=mij) update_arb(Vnod,i_arb,i_pos,st,mij,nod*2);
else update_arb(Vnod,i_arb,i_pos,mij+1,dr,nod*2+1);
if (val[Arb[i_arb][nod*2]]>val[Arb[i_arb][nod*2+1]])
Arb[i_arb][nod]=Arb[i_arb][nod*2];
else Arb[i_arb][nod]=Arb[i_arb][nod*2+1];
}
int result,res_ind;
void query_arb(int X,int Y,int i_arb,int st,int dr,int nod) {
int mij=(st+dr)/2;
if (st>=X&&dr<=Y) {
if (val[Arb[i_arb][nod]]>result) {
result=val[Arb[i_arb][nod]];
res_ind=Arb[i_arb][nod];
}
return ;
}
if (X<=mij) query_arb(X,Y,i_arb,st,mij,nod*2);
if (Y>mij) query_arb(X,Y,i_arb,mij+1,dr,nod*2+1);
}
void update(int nod,int value) {
int _lant=lant_ind[nod];
int _pos=lant_pos[nod];
update_arb(nod,_lant,_pos,1,grad[_lant],1);
}
int query(int nod1,int nod_root) {
int fin_res=0,fin_ind=0;
while (true) {
if (lant_ind[nod1]==lant_ind[nod_root]) {
result=res_ind=0;
int x1=lant_pos[nod1],x2=lant_pos[nod_root];
if (x1>x2) swap(x1,x2);
query_arb(x1,x2,lant_ind[nod1],1,grad[lant_ind[nod1]],1);
if (result>=fin_res) {
fin_res=result;
fin_ind=res_ind;
}
return fin_ind;
}
result=res_ind=0;
int x2=grad[lant_ind[nod1]],x1=lant_pos[nod1];
query_arb(x1,x2,lant_ind[nod1],1,grad[lant_ind[nod1]],1);
if (result>fin_res) {
fin_res=result;
fin_ind=res_ind;
}
nod1=father[lant_up[lant_ind[nod1]]];
}
}
int main() {
f>>n>>nrq;
for(i=1; i<=n; ++i) f>>val[i];
for(i=1; i<n; ++i) {
int xx,yy;
f>>xx>>yy;
H[xx].pb(yy);
H[yy].pb(xx);
}
dfs(1,1);
for(i=1; i<=k; ++i) rmq[0][i]=st[i];
for(int lgs=1; (1<<(lgs))<=k; lgs++)
for(int j=1; j<=k; ++j) {
if (j+(1<<(lgs-1))>k) {
rmq[lgs][j]=rmq[lgs-1][j];
continue;
}
if (level[rmq[lgs-1][j]]<level[rmq[lgs-1][j+(1<<(lgs-1))]])
rmq[lgs][j]=rmq[lgs-1][j];
else rmq[lgs][j]=rmq[lgs-1][j+(1<<(lgs-1))];
}
for(i=2; i<=k; ++i) mpow[i]=mpow[i/2]+1;
for(i=1; i<=n; ++i) viz[i]=false;
heavy_path(1);
// cout<<get_lca(6 ,9);
//cout<<get_lca(1,9)<<'\n';
//for(i=1; i<=n; ++i) cout<<lant_ind[i]<<" ";
for(i=1; i<=nr_lant; ++i)
for(int j=1; j<=grad[i]*5; ++j) Arb[i].pb(0);
for(i=1; i<=n; ++i)
update(i,val[i]);
for(i=1; i<=n; ++i)
if (lant_pos[i]==grad[lant_ind[i]]) lant_up[lant_ind[i]]=i;
//cout<<nrq<<'\n';
for(int tt=1; tt<=nrq; ++tt) {
int tip,v1,v2;
f>>tip>>v1>>v2;
if (tip==0) {
val[v1]=v2;
update(v1,v2);
} else {
int nod1=query(v1,get_lca(v1,v2));
int nod2=query(v2,get_lca(v1,v2));
if (val[nod1]>val[nod2]) g<<val[nod1];
else g<<val[nod2];
g<<'\n';
}
}
f.close();
g.close();
return 0;
}