#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5;
ifstream fin( "heavypath.in" );
ofstream fout( "heavypath.out" );
int n;
int val[MAXN+1], depth[MAXN+1], parent[MAXN+1], sz[MAXN+1], heavyChild[MAXN+1], valueInOrder[MAXN+1], chain[MAXN+1];
int label[MAXN+1], nr = 0;
int maxi[MAXN+1], indexx[MAXN+1];
int aint[2*MAXN+1];
vector <int> edges[MAXN+1];
void build( int node, int left, int right ) {
if( left == right ) {
aint[node] = valueInOrder[left];
return;
}
int mid, leftSon, rightSon;
mid = ( left + right ) / 2;
leftSon = node + 1;
rightSon = node + 2 * ( mid - left + 1 );
build( leftSon, left, mid );
build( rightSon, mid + 1, right );
aint[node] = max( aint[leftSon], aint[rightSon] );
}
void update( int node, int left, int right, int poz, int val ) {
if( left == right ) {
aint[node] = val;
return;
}
int mid, leftSon, rightSon;
mid = ( left + right ) / 2;
leftSon = node + 1;
rightSon = node + 2 * ( mid - left + 1 );
if( poz <= mid )
update( leftSon, left, mid, poz, val );
else
update( rightSon, mid + 1, right, poz, val );
aint[node] = max( aint[leftSon], aint[rightSon] );
}
int query( int node, int left, int right, int qleft, int qright ) {
if( left >= qleft && right <= qright )
return aint[node];
if( left > qright || right < qleft )
return -1;
int ans = -1;
int mid, leftSon, rightSon;
mid = ( left + right ) / 2;
leftSon = node + 1;
rightSon = node + 2 * ( mid - left + 1 );
if( qleft <= mid )
ans = max( ans, query( leftSon, left, mid, qleft, qright ) );
if( qright > mid )
ans = max( ans, query( rightSon, mid + 1, right, qleft, qright ) );
return ans;
}
void dfs( int node, int height ) {
depth[node] = height;
sz[node] = 1;
maxi[node] = indexx[node] = -1;
for( auto vec: edges[node] ) {
if( vec != parent[node] ) {
parent[vec] = node;
dfs( vec, height + 1 );
sz[node] += sz[vec];
if( sz[vec] > maxi[node] ) {
maxi[node] = sz[vec];
indexx[node] = vec;
}
}
}
heavyChild[node] = indexx[node];
}
void dfs_labels( int node ) {
label[node] = nr++;
if( heavyChild[node] != -1 ) {
chain[heavyChild[node]] = chain[node];
dfs_labels( heavyChild[node] );
}
for( auto vec: edges[node] ) {
if( vec != parent[node] && vec != heavyChild[node] ) {
dfs_labels( vec );
}
}
}
int solve( int a, int b ) {
if( chain[a] == chain[b] ) {
if( label[a] > label[b] )
swap( a, b );
return query( 0, 0, n - 1, label[a], label[b] );
}
if( depth[chain[a]] < depth[chain[b]] )
swap( a, b );
return max( query( 0, 0, n - 1, label[chain[a]], label[a] ), solve( parent[chain[a]], b ) );
}
int main() {
int q, i, x, y, op;
fin >> n >> q;
for( i = 0; i < n; i++ )
fin >> val[i], chain[i] = i;
for( i = 0; i < n - 1; i++ ) {
fin >> x >> y;
x--, y--;
edges[x].push_back( y );
edges[y].push_back( x );
}
dfs( 0, 0 );
dfs_labels( 0 );
for( i = 0; i < n; i++ )
valueInOrder[label[i]] = val[i];
//for( i = 0; i < n; i++ )
//cout << valueInOrder[i] << " ";
build( 0, 0, n - 1 );
//cout << query( 0, 0, n - 1, 0, 2 );
for( i = 0; i < q; i++ ) {
fin >> op >> x >> y;
if( op == 0 )
update( 0, 0, n - 1, label[x-1], y );
else
fout << solve( x - 1, y - 1 ) << "\n";
}
return 0;
}