#include <stdio.h>
#include <vector>
#define pb push_back
#define Nmax 100005
using namespace std;
int N,M,rez_query,Nr_lanturi;
vector< int > Arbint[Nmax];
vector< int > v[Nmax],Lant[Nmax];
int Val[Nmax],use[Nmax],Niv[Nmax],Weight[Nmax];
int In_ce_lant[Nmax],Poz_in_lant[Nmax],Before_lant[Nmax],Start_lant[Nmax];
void Read(){
int i,x,y;
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
scanf("%d%d",&N,&M);
for(i=1;i<=N;++i) scanf("%d",&Val[i]);
for(i=1;i<N;++i){
scanf("%d%d",&x,&y);
v[x].pb(y);
v[y].pb(x);
}
}
void Df(int x){
vector< int >:: iterator it;
use[x]=1;
if( v[x].size() == 1 && x!=1 )
{
Nr_lanturi ++;
In_ce_lant[x]=Nr_lanturi;
Lant[Nr_lanturi].pb(x);
Poz_in_lant[x]=1;
Start_lant[In_ce_lant[x]]=x;
Weight[x]=1;
return;
}
int wmax=0, fiu_wmax=0;
for(it=v[x].begin(); it!=v[x].end(); ++it)
if( ! use[ *it ] )
{
Niv[ *it ] = Niv[x] + 1;
Df(*it);
Weight[x] += Weight[*it];
if( Weight[*it] > wmax )
{
wmax = Weight[*it];
fiu_wmax = *it;
}
}
In_ce_lant[x]=In_ce_lant[fiu_wmax];
Poz_in_lant[x] = Poz_in_lant[Lant[In_ce_lant[x]].back()]+1;
Lant[In_ce_lant[x]].pb(x);
Start_lant[In_ce_lant[x]]=x;
for(it=v[x].begin(); it!=v[x].end(); ++it)
if( Niv[*it] > Niv[x] && *it != fiu_wmax )
{
Before_lant[In_ce_lant[*it]] = x;
Start_lant[In_ce_lant[*it]]=*it;
}
}
inline void Update(int care_arb, int nod, int l,int r, int poz,int val){
if( l == r ){
Arbint[care_arb][nod] = val;
return;
}
int m=l+(r-l)/2;
if( poz<=m ) Update(care_arb, 2*nod, l, m, poz, val);
else Update(care_arb, 2*nod+1, m+1, r, poz, val);
Arbint[care_arb][nod] = max( Arbint[care_arb][2*nod], Arbint[care_arb][2*nod+1] );
}
inline void Query(int care_arb, int nod, int l, int r, int x, int y){
if( x<=l && r<= y ){
rez_query = max( rez_query, Arbint[care_arb][nod] );
return;
}
int m=l+(r-l)/2;
if( x<=m ) Query( care_arb, 2*nod, l, m, x, y);
if( m<y ) Query( care_arb, 2*nod+1, m+1, r, x, y);
}
void Make_arbint(){
vector< int >:: iterator it;
int i;
for(i=1;i<=Nr_lanturi;++i){
Arbint[i].reserve( Lant[i].size() * 4 );
for(it=Lant[i].begin(); it!=Lant[i].end(); ++it)
Update( i, 1, 1, Lant[i].size(), Poz_in_lant[*it], Val[*it]);
}
}
inline void Solve(){
int i,tip,x,y;
for(i=1;i<=M;++i){
scanf("%d%d%d",&tip,&x,&y);
if( tip == 0 ){
Update( In_ce_lant[x], 1, 1, Lant[In_ce_lant[x]].size(), Poz_in_lant[x], y );
}
else{
rez_query = 0;
while( 1 ){
if( In_ce_lant[x] == In_ce_lant[y] ){
if( Poz_in_lant[x] > Poz_in_lant[y] ) swap(x,y);
Query( In_ce_lant[x], 1, 1, Lant[In_ce_lant[x]].size(), Poz_in_lant[x],Poz_in_lant[y]);
break;
}
if( Niv[Before_lant[In_ce_lant[x]]] < Niv[Before_lant[In_ce_lant[y]]])
swap(x,y);
Query( In_ce_lant[x], 1, 1, Lant[In_ce_lant[x]].size(), Poz_in_lant[x], Lant[In_ce_lant[x]].size() );
x = Before_lant[In_ce_lant[x]];
}
printf("%d\n", rez_query);
}
}
}
int main(){
Read();
Niv[1]=1, Df(1);
Make_arbint();
Solve();
fclose(stdin); fclose(stdout);
return 0;
}