#include<bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int DIM = 1e5 + 5;
int N, M, Pos[DIM], Father_Path[DIM], S[DIM], V[DIM], Ind, Wh_Path[DIM], Lvl[DIM];
vector<int> Aint_Path[DIM], Path[DIM], edge[DIM];
void dfs( int nod, int tata ){
S[nod] = 1;
int link_nod = -1, maxs = 0;
for( int i = 0; i < edge[nod].size(); i++ ){
int son = edge[nod][i];
if( son != tata ){
Lvl[son] = Lvl[nod] + 1;
dfs( son, nod );
S[nod] += S[son];
if( maxs < S[son] )
maxs = S[son], link_nod = son;
}
}
if( link_nod == -1 ){
Wh_Path[nod] = ++Ind;
Path[Ind].push_back( nod );
return;
}
Wh_Path[nod] = Wh_Path[link_nod];
Path[ Wh_Path[nod] ].push_back( nod );
for( int i = 0; i < edge[nod].size(); i++ ){
int son = edge[nod][i];
if( son != tata && son != link_nod )
Father_Path[ Wh_Path[son] ] = nod;
}
return;
}
void debug1(){
fout << Ind << "\n";
for( int i = 1; i <= Ind; i++ ){
fout << "Father of path is :" << Father_Path[i] << "\n";
fout << "Nodes of path are :";
reverse( Path[i].begin(), Path[i].end() );
for( int j = 0; j < Path[i].size(); j++ )
fout << Path[i][j] << " ";
fout << "\n\n";
}
}
void build( int k, int nod, int st, int dr ){
int Nst = (nod<<1);
int Ndr = ((nod<<1)|1);
if( st == dr ){
Aint_Path[k][nod] = V[ Path[k][st] ];
}else{
int mid = ( st + dr ) >> 1;
build( k, Nst, st, mid + 0 );
build( k, Ndr, mid + 1, dr );
Aint_Path[k][nod] = max( Aint_Path[k][Nst], Aint_Path[k][Ndr] );
}
}
void update( int k, int nod, int st, int dr, int p ){
int Nst = (nod<<1);
int Ndr = ((nod<<1)|1);
if( st == dr ){
Aint_Path[k][nod] = V[ Path[k][st] ];
}else{
int mid = ( st + dr ) >> 1;
if( p <= mid )
update( k, Nst, st, mid + 0, p );
else
update( k, Ndr, mid + 1, dr, p );
Aint_Path[k][nod] = max( Aint_Path[k][Nst], Aint_Path[k][Ndr] );
}
}
int query( int k, int nod, int st, int dr, int a, int b ){
int Nst = (nod<<1);
int Ndr = ((nod<<1)|1);
int Sol = 0;
if( a <= st && dr <= b ){
Sol = Aint_Path[k][nod];
}else{
int mid = ( st + dr ) >> 1;
if( a <= mid )
Sol = max( Sol, query( k, Nst, st, mid + 0, a, b ) );
if( b > mid )
Sol = max( Sol, query( k, Ndr, mid + 1, dr, a, b ) );
}
return Sol;
}
int get_ans( int x, int y ){
int Ans = 0;
while( Wh_Path[x] != Wh_Path[y] ){
if( Lvl[ Father_Path[ Wh_Path[x] ] ] > Lvl[ Father_Path[ Wh_Path[y] ] ] ){
Ans = max( Ans, query( Wh_Path[x], 1, 0, Path[ Wh_Path[x] ].size() - 1, 0, Pos[x] ) );
x = Father_Path[ Wh_Path[x] ];
}else{
Ans = max( Ans, query( Wh_Path[y], 1, 0, Path[ Wh_Path[y] ].size() - 1, 0, Pos[y] ) );
y = Father_Path[ Wh_Path[y] ];
}
}
if( Pos[x] > Pos[y] )
swap( x, y );
Ans = max( Ans, query( Wh_Path[x], 1, 0, Path[ Wh_Path[x] ].size() - 1, Pos[x], Pos[y] ) );
return Ans;
}
int main(){
fin >> N >> M;
for( int i = 1; i <= N; i++ )
fin >> V[i];
for( int i = 1; i < N; i++ ){
int x, y; fin >> x >> y;
edge[x].push_back( y );
edge[y].push_back( x );
}
Lvl[1] = 1;
dfs( 1, 0 );
for( int i = 1; i <= Ind; i++ ){
reverse( Path[i].begin(), Path[i].end() );
for( int j = 0; j < Path[i].size(); j++ )
Pos[ Path[i][j] ] = j;
Aint_Path[i].resize( Path[i].size() * 4 + 5, 0 );
build( i, 1, 0, Path[i].size() - 1 );
}
while( M-- ){
int op, x, y; fin >> op >> x >> y;
if( op == 0 ){
V[x] = y;
update( Wh_Path[x], 1, 0, Path[ Wh_Path[x] ].size() - 1, Pos[x] );
}else
fout << get_ans( x, y ) << "\n";
}
return 0;
}