#include <stdio.h>
#include <assert.h>
#include <vector>
#include <algorithm>
struct Splay {
struct Node {
int c[2], par;
int flip;
int key, max;
Node(): par(0), flip(false), key(0), max(0) { c[0] = c[1] = 0; }
};
std::vector<Node> t;
Splay( int n ): t(n + 1) {}
void push_flip( int x ) {
if( !x ) return;
t[x].flip ^= 1;
}
void push( int x ) {
if( !t[x].flip ) return;
std::swap( t[x].c[0], t[x].c[1] );
t[x].flip = false;
push_flip( t[x].c[0] );
push_flip( t[x].c[1] );
}
void pull( int x ) {
int left = t[x].c[0], right = t[x].c[1];
t[x].max = t[x].key;
if( left ) t[x].max = std::max( t[x].max, t[left].max );
if( right ) t[x].max = std::max( t[x].max, t[right].max );
}
int side( int x ) {
int par = t[x].par;
if( t[par].c[0] == x ) return 0;
if( t[par].c[1] == x ) return 1;
return -1;
}
void link( int x, int y, int side ) {
if( y ) t[y].par = x;
if( x && ~side ){
t[x].c[side] = y;
pull( x );
}
}
void zig( int x ) {
int y = t[x].par, sx = side( x );
int up = t[y].par, sy = side( y ), mij = t[x].c[!sx];
link( y, mij, sx );
link( x, y, !sx );
link( up, x, sy );
}
void splay( int x ) {
while( ~side( x ) ){
int y = t[x].par;
if( !~side( y ) ){
push( y );
push( x );
zig( x );
continue;
}
int z = t[y].par;
push( z );
push( y );
push( x );
int sx = side( x ), sy = side( y );
zig( sx == sy ? y : x );
zig( x );
}
}
};
struct LinkCut : Splay {
LinkCut( int n ): Splay(n) {}
void expose( int uu ) {
int u = uu, prev = 0;
while( u ) {
splay( u );
push( u );
t[u].c[1] = prev;
pull( u );
prev = u;
u = t[u].par;
}
splay( uu );
}
void reroot( int u ) {
expose( u );
push_flip( u );
}
void Link( int a, int b ) {
expose( a );
reroot( b );
// assert( side( a ) == -1 );
// assert( side( b ) == -1 );
t[b].par = a; // soft link
}
int Path( int a, int b ) {
reroot( a );
expose( b );
return t[b].max;
}
void Update( int u, int newv ) {
expose( u );
t[u].key = newv;
pull( u );
}
};
int main() {
FILE *fin = fopen( "heavypath.in", "r" );
FILE *fout = fopen( "heavypath.out", "w" );
int n, m;
fscanf( fin, "%d%d", &n, &m );
LinkCut zile(n);
for( int u = 1; u <= n; u++ ){
int x;
fscanf( fin, "%d", &x );
zile.Update( u, x );
}
for( int i = 1; i < n; i++ ){
int a, b;
fscanf( fin, "%d%d", &a, &b );
zile.Link( a, b );
}
for( int i = 0; i < m; i++ ){
int task;
fscanf( fin, "%d", &task );
if( task == 0 ){
int u, newv;
fscanf( fin, "%d%d", &u, &newv );
zile.Update( u, newv );
}else{// if( task == 1 ){
int a, b;
fscanf( fin, "%d%d", &a, &b );
fprintf( fout, "%d\n", zile.Path( a, b ) );
}
}
fclose( fin );
fclose( fout );
return 0;
}