#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
ifstream fin( "heavypath.in" ); ofstream fout( "heavypath.out" );
typedef vector< int > graf;
const int nmax = 1e5;
int n;
bool viz[ nmax + 1 ];
int dp[ nmax + 1 ];
int v[ nmax + 1 ], ad[ nmax + 1 ];
int lant[ nmax + 1 ], ind[ nmax + 1 ];
graf g[ nmax + 1 ];
inline int max2( int a, int b ) {
return ( a > b ? a : b );
}
class Lant{
public:
int tata;
vector< int > nodes;
vector< int > aint;
inline void init( int dim ) {
aint.resize( 4 * dim + 1 );
}
inline void update( int nod, int x, int y, int pos, int val ) {
if ( x == y ) {
aint[ nod ] = val;
return ;
}
int mij = (x + y) / 2;
if ( pos <= mij ) {
update( 2 * nod, x, mij, pos, val );
} else {
update( 2 * nod + 1, mij + 1, y, pos, val );
}
aint[ nod ] = max2( aint[ 2 * nod ], aint[ 2 * nod + 1 ] );
}
inline int query( int nod, int x, int y, int st, int dr ) {
int ans = 0;
if ( st <= x && y <= dr ) {
return aint[ nod ];
}
int mij = (x + y) / 2;
if ( st <= mij ) {
ans = max2( ans, query( 2 * nod, x, mij, st, dr ) );
}
if ( dr >= mij + 1 ) {
ans = max2( ans, query( 2 * nod + 1, mij + 1, y, st, dr ) );
}
return ans;
}
} l[ nmax + 1 ];
void dfs( int nod, int tata = 0 ) {
viz[ nod ] = 1;
dp[ nod ] = 1;
int fiug, sol = -1;
for( auto it : g[ nod ] ) {
if ( it != tata ) {
ad[ it ] = ad[ nod ] + 1;
dfs( it, nod );
dp[ nod ] += dp[ it ];
if ( dp[ it ] > sol ) {
fiug = it;
sol = dp[ it ];
}
}
}
if ( sol == -1 ) {
l[ nod ].tata = 0;
lant[ nod ] = nod;
} else {
lant[ nod ] = lant[ fiug ];
for( auto it : g[ nod ] ) {
if ( it != tata && it != fiug ) {
l[ lant[ it ] ].tata = nod;
}
}
}
l[ lant[ nod ] ].nodes.push_back( nod );
}
void aranjeaza_lanturi() {
for( int i = 1; i <= n; ++ i ) {
reverse( l[ i ].nodes.begin(), l[ i ].nodes.end() );
int dim = ( int )l[ i ].nodes.size();
l[ i ].init( dim );
for( vector< int >::iterator it = l[ i ].nodes.begin(); it != l[ i ].nodes.end(); ++ it ) {
ind[ *it ] = it - l[ i ].nodes.begin() + 1;
l[ i ].update( 1, 1, dim, ind[ *it ], v[ *it ] );
}
}
}
int solve( int x, int y ) {
int ans = -1;
while ( lant[ x ] != lant[ y ] ) {
if ( ad[ l[ lant[ x ] ].tata ] > ad[ l[ lant[ y ] ].tata ] ) {
swap( x, y );
}
ans = max2( ans, l[ lant[ y ] ].query( 1, 1, ( int )l[ lant[ y ] ].nodes.size(), 1, ind[ y ] ) );
y = l[ lant[ y ] ].tata;
}
if ( ind[ x ] > ind[ y ] ) {
swap( x, y );
}
ans = max2( ans, l[ lant[ x ] ].query( 1, 1, ( int )l[ lant[ x ] ].nodes.size(), ind[ x ], ind[ y ] ) );
return ans;
}
int main() {
int m;
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;
g[ x ].push_back( y );
g[ y ].push_back( x );
}
ad[ 1 ] = 1;
dfs( 1 );
aranjeaza_lanturi();
while ( m -- ) {
int t, x, y;
fin >> t >> x >> y;
if ( t == 0 ) {
l[ lant[ x ] ].update( 1, 1, ( int )l[ lant[ x ] ].nodes.size(), ind[ x ], y );
} else {
fout << solve( x, y ) << "\n";
}
}
fin.close();
fout.close();
return 0;
}