#include<bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int DIM = 1e5 + 5;
int Wh_Path[DIM], N, M, S[DIM], arr[DIM], Pos_Path[DIM], K, ans;
int Niv[DIM], Rmq[19][DIM], Log;
vector<int> Path[DIM], Aint_Path[DIM], edge[DIM];
void dfs( int nod, int nv ){
S[nod] = 1;
Niv[nod] = nv;
bool ok = false;
for( int i = 0; i < edge[nod].size(); i++ ){
if( edge[nod][i] != Rmq[0][nod] ){
ok = true;
Rmq[0][ edge[nod][i] ] = nod;
dfs( edge[nod][i], nv + 1 );
S[nod] += S[ edge[nod][i] ];
}
}
if( ok == false ){
K++;
Path[K].push_back( nod );
Wh_Path[nod] = K;
Pos_Path[nod] = Path[K].size();
}else{
int mx = 0, x = -1;
for( int i = 0; i < edge[nod].size(); i++ ){
if( edge[nod][i] == Rmq[0][nod] )
continue;
if( mx < S[ edge[nod][i] ] )
mx = S[ edge[nod][i] ], x = edge[nod][i];
}
Path[ Wh_Path[x] ].push_back( nod );
Wh_Path[nod] = Wh_Path[x];
Pos_Path[nod] = Path[ Wh_Path[x] ].size();
}
}
void build_aint( int k, int nod, int st, int dr ){
if( st == dr ){
Aint_Path[k][nod] = arr[ Path[k][st - 1] ];
}else{
int mid = ( st + dr ) >> 1;
build_aint( k, (nod<<1)^0, st, mid + 0 );
build_aint( k, (nod<<1)|1, mid + 1, dr );
Aint_Path[k][nod] = max( Aint_Path[k][(nod<<1)^0], Aint_Path[k][(nod<<1)|1] );
}
}
void update_aint( int k, int nod, int st, int dr, int p, int x ){
if( st == dr ){
Aint_Path[k][nod] = x;
}else{
int mid = ( st + dr ) >> 1;
if( p <= mid )
update_aint( k, (nod<<1)^0, st, mid + 0, p, x );
else
update_aint( k, (nod<<1)|1, mid + 1, dr, p, x );
Aint_Path[k][nod] = max( Aint_Path[k][(nod<<1)^0], Aint_Path[k][(nod<<1)|1] );
}
}
inline int lca( int x, int y ){
if( Niv[x] > Niv[y] )
swap( x, y );
for( int k = Log; k >= 0; k-- )
if( Niv[ Rmq[k][y] ] >= Niv[x] )
y = Rmq[k][y];
if( x == y )
return x;
for( int k = Log; k >= 0; k-- ){
if( Rmq[k][x] != Rmq[k][y] ){
x = Rmq[k][x];
y = Rmq[k][y];
}
}
if( x == y )
return x;
return Rmq[0][x];
}
void query_aint( int k, int nod, int st, int dr, int a, int b ){
if( a <= st && dr <= b ){
ans = max( ans, Aint_Path[k][nod] );
}else{
int mid = ( st + dr ) >> 1;
if( a <= mid )
query_aint( k, (nod<<1)^0, st, mid + 0, a, b );
if( b > mid )
query_aint( k, (nod<<1)|1, mid + 1, dr, a, b );
}
}
void solve_query( int x, int y ){
int z = lca( x, y );
ans = 0;
while( Wh_Path[x] != Wh_Path[z] ){
query_aint( Wh_Path[x], 1, 1, Path[ Wh_Path[x] ].size(), Pos_Path[x], Path[ Wh_Path[x] ].size() );
x = Rmq[0][ Path[ Wh_Path[x] ].back() ];
}
while( Wh_Path[y] != Wh_Path[z] ){
query_aint( Wh_Path[y], 1, 1, Path[ Wh_Path[y] ].size(), Pos_Path[y], Path[ Wh_Path[y] ].size() );
y = Rmq[0][ Path[ Wh_Path[y] ].back() ];
}
if( Pos_Path[x] > Pos_Path[y] )
swap(x, y);
query_aint( Wh_Path[x], 1, 1, Path[ Wh_Path[x] ].size(), Pos_Path[x], Pos_Path[y] );
}
int main(){
fin >> N >> M;
for( int i = 1; i <= N; i++ )
fin >> arr[i];
for( int i = 1; i < N; i++ ){
int x, y; fin >> x >> y;
edge[x].push_back( y );
edge[y].push_back( x );
}
dfs( 1, 1 );
Log = 0;
while( (1<<Log) <= N )
Log++;
for( int k = 1; k <= Log; k++ )
for( int i = 1; i <= N; i++ )
Rmq[k][i] = Rmq[k - 1][ Rmq[k - 1][i] ];
for( int i = 1; i <= K; i++ ){
Aint_Path[i].resize( (int)(4 * Path[i].size()), 0 );
build_aint( i, 1, 1, Path[i].size() );
}
for( int i = 1; i <= M; i++ ){
int t, x, y; fin >> t >> x >> y;
if( t == 0 ){
update_aint( Wh_Path[x], 1, 1, Path[ Wh_Path[x] ].size(), Pos_Path[x], y );
}else{
solve_query( x, y );
fout << ans << "\n";
}
}
return 0;
}