#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int NMAX = 100000;
class AINT{
public:
int *tree;
AINT (int n) {
tree = new int[4 * n];
}
void update( int node, int st, int dr, int poz, int val ) {
if( st == dr ) {
tree[node] = val;
return ;
}
int mid = (st + dr) / 2;
if( poz <= mid )
update(2*node, st, mid, poz, val);
else
update(2*node + 1, mid + 1, dr, poz, val);
tree[node] = max( tree[2*node], tree[2*node + 1] );
}
int query( int node, int st, int dr, int left, int right ) {
if( dr < left || st > right )
return 0;
if( left <= st && dr <= right )
return tree[node];
int mid = (st + dr) / 2;
return max( query(2*node, st, mid, left, right),
query(2*node + 1, mid + 1, dr, left, right) );
}
};
vector<int> G[NMAX + 1];
vector<vector<int>> lanturi;
vector<AINT> path;
int tata[NMAX + 1], values[NMAX + 1], level[NMAX + 1], carelant[NMAX + 1], pos[NMAX + 1], k;
int dfs( int node, int father ) {
int nrd = 1, maxim = 0, tolant;
tata[node] = father;
for( const auto &it : G[node] ) {
if( it != father ) {
level[it] = 1 + level[node];
int val = dfs( it, node );
nrd += val;
if( val > maxim ) {
maxim = val;
tolant = carelant[it];
}
}
}
if( maxim == 0 ) {
lanturi.push_back({0, node});
carelant[node] = k ++;
}
else {
carelant[node] = tolant;
lanturi[tolant].push_back(node);
}
return nrd;
}
bool cmp( int a, int b ) {
return level[a] < level[b];
}
int raspuns( int x, int y ) {
int bucketx = carelant[x];
int buckety = carelant[y];
int parentx = lanturi[bucketx][1];
int parenty = lanturi[buckety][1];
int sz = lanturi[bucketx].size() - 1;
if( level[parentx] < level[parenty] )
swap(x, y), swap(parentx, parenty), swap(bucketx, buckety);
if( parentx == parenty ) {
int st = min(pos[x], pos[y]);
int dr = max(pos[x], pos[y]);
return path[bucketx].query(1, 1, sz, st, dr);
}
int nextnode = tata[parentx];
return max( path[bucketx].query(1, 1, sz, 1, pos[x] ), raspuns(nextnode, y) );
}
int main() {
int n, m;
fin>>n>>m;
for( int i = 1; i <= n; i ++ )
fin>>values[i];
for( int i = 1; i <= n - 1; i ++ ) {
int u, v;
fin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, 0);
for( int i = 0; i < k; i ++ ) {
sort(lanturi[i].begin() + 1, lanturi[i].end(), cmp);
int sz = lanturi[i].size();
path.push_back(AINT(sz - 1));
for( int j = 1; j < sz; j ++ ) {
int node = lanturi[i][j];
pos[node] = j;
path[i].update( 1, 1, sz - 1, j, values[node] );
}
}
for( int i = 1; i <= m; i ++ ) {
int op, x, y;
fin>>op>>x>>y;
if( op == 0 ) {
int bucket = carelant[x];
int to = pos[x];
path[bucket].update(1, 1, lanturi[bucket].size() - 1, to, y);
}
else {
fout<<raspuns(x, y)<<"\n";
}
}
return 0;
}