#include<stdio.h>
#include<vector>
#include<algorithm>
#define maxn 100005
#define pb push_back
using namespace std;
FILE*f=fopen("heavypath.in","r");
FILE*g=fopen("heavypath.out","w");
int n,m,i,x,y,paths,tip,poz_upd,val,a,b;
int v[maxn],Niv[maxn],subarb[maxn],lant[maxn],poz[maxn],up[maxn];
vector<int>G[maxn],P[maxn],Arb[maxn];
inline void citire () {
fscanf(f,"%d %d",&n,&m);
for ( i = 1 ; i <= n ; ++i ){
fscanf(f,"%d",&v[i]);
}
for ( i = 1 ; i < n ; ++i ){
fscanf(f,"%d %d",&x,&y);
G[x].pb(y);
G[y].pb(x);
}
}
void dfs ( int nod , int niv , int t ){
Niv[nod] = niv; subarb[nod] = 1;
for ( vector<int>::iterator itt = G[nod].begin() ; itt != G[nod].end() ; ++itt ){
int nodvcn = (*itt);
if ( nodvcn != t ){
up[nodvcn] = nod;
dfs(nodvcn,niv+1,nod);
subarb[nod] += subarb[nodvcn];
}
}
if ( G[nod].size() == 1 && nod != 1 ){
lant[nod] = ++paths; P[ paths ].pb(0);
P[ paths ].pb(nod); poz[nod] = 1;
return ;
}
int hv = 0;
for ( vector<int>::iterator itt = G[nod].begin() ; itt != G[nod].end() ; ++itt ){
int nodvcn = (*itt);
if ( nodvcn != t ){
if ( subarb[nodvcn] > subarb[hv] ){
hv = nodvcn;
}
}
}
lant[nod] = lant[hv];
P[ lant[nod] ].pb(nod); poz[nod] = P[ lant[nod] ].size() - 1;
}
void init ( int nod , int st , int dr , int ind ){
if ( st == dr ){
Arb[ind][nod] = v[ P[ind][st] ];
return ;
}
int mij = (st + dr) >> 1;
int nodst = nod << 1;
int noddr = nodst + 1;
init(nodst,st,mij,ind);
init(noddr,mij+1,dr,ind);
Arb[ind][nod] = max(Arb[ind][nodst],Arb[ind][noddr]);
}
void update ( int nod , int st , int dr , int ind ){
if ( st == dr ){
Arb[ind][nod] = val;
return ;
}
int mij = (st + dr) >> 1;
int nodst = nod << 1;
int noddr = nodst + 1;
if ( poz_upd <= mij ){
update(nodst,st,mij,ind);
}
else{
update(noddr,mij+1,dr,ind);
}
Arb[ind][nod] = max(Arb[ind][nodst],Arb[ind][noddr]);
}
void query ( int nod , int st , int dr , int ind , int &sol ){
if ( a <= st && dr <= b ){
sol = max(sol,Arb[ind][nod]);
return ;
}
int mij = (st + dr) >> 1;
int nodst = nod << 1;
int noddr = nodst + 1;
if ( a <= mij ){
query(nodst,st,mij,ind,sol);
}
if ( b > mij ){
query(noddr,mij+1,dr,ind,sol);
}
}
inline int find_max ( int x , int y ){
int sol = 0;
for ( ; ; ){
if ( lant[x] == lant[y] ){
int u = lant[x];
a = min(poz[x],poz[y]); b = max(poz[x],poz[y]);
query(1,1,P[u].size()-1,u,sol);
break ;
}
int t1 = P[lant[x]][1];
int t2 = P[lant[y]][1];
if ( Niv[t1] < Niv[t2] ){
swap(x,y);
}
a = 1; b = poz[x]; query(1,1,P[lant[x]].size()-1,lant[x],sol);
x = up[ P[lant[x]][1] ];
}
return sol;
}
inline void solve () {
dfs(1,1,0);
for ( int i = 1 ; i <= paths ; ++i ){
reverse(P[i].begin()+1,P[i].end());
Arb[i].resize(4*(P[i].size()+1));
init(1,1,P[i].size()-1,i);
}
for ( int i = 1 ; i <= n ; ++i ){
poz[i] = P[lant[i]].size() - poz[i];
}
for ( int i = 1 ; i <= m ; ++i ){
fscanf(f,"%d %d %d",&tip,&x,&y);
if ( !tip ){
poz_upd = poz[x]; val = y;
update(1,1,P[ lant[x] ].size()-1,lant[x]);
}
else{
fprintf(g,"%d\n",find_max(x,y));
}
}
}
int main () {
citire();
solve();
fclose(f);
fclose(g);
return 0;
}