#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
#define leftson (2 * node)
#define rightson (2 * node + 1)
const int nmax = 100010;
int n, m, v[nmax], a, b, t, x, y, aint[4 * nmax], level[nmax];
vector<int> g[nmax], chain[nmax];
bool used[nmax];
int sub[nmax], nrch, chainstart[nmax], chainfather[nmax], chainpos[nmax], chainindex[nmax], chainsize[nmax];
void dfs(int node, int father)
{
level[node] = level[father] + 1;
sub[node] = 1;
bool is_leaf = 1;
int heaviest = -1;
for (int vec : g[node])
{
if (vec == father) continue;
is_leaf = 0;
dfs(vec, node);
if (heaviest == -1 || sub[vec] > sub[heaviest])
heaviest = vec;
sub[node] += sub[vec];
}
if (is_leaf)
{
++ nrch;
chain[nrch].push_back(node);
chainindex[node] = nrch;
chainsize[nrch] ++;
}else
{
for (int vec : g[node])
{
if (vec == father) continue;
if (vec == heaviest)
{
chainindex[node] = chainindex[vec];
chain[chainindex[node]].push_back(node);
chainsize[chainindex[node]] ++;
}else
chainfather[chainindex[vec]] = node;
}
}
}
void update(int node, int left, int right, int shift, int pos, int val)
{
if (left == right)
{
aint[node + shift] = val;
return ;
}
int mid = (left + right)/ 2;
if (pos <= mid)
update(leftson, left, mid, shift, pos, val);
else
update(rightson, mid + 1, right, shift, pos, val);
aint[node + shift] = max(aint[leftson + shift], aint[rightson + shift]);
}
int query(int node, int left, int right, int shift, int leftb, int rightb)
{
if (leftb <= left && right <= rightb)
return aint[node + shift];
int mid = (left + right) / 2, now = 0;
if (leftb <= mid)
now = max(now, query(leftson, left, mid, shift, leftb, rightb));
if (mid < rightb)
now = max(now, query(rightson, mid + 1, right, shift, leftb, rightb));
return now;
}
void build_decomp()
{
for (int i = 1; i <= nrch; ++ i)
{
chainstart[i] = chainstart[i - 1] + 4 * chainsize[i - 1];
reverse(chain[i].begin(), chain[i].end());
for (int j = 0; j < chain[i].size(); ++ j)
{
chainpos[chain[i][j]] = j + 1;
update(1, 1, chainsize[i], chainstart[i], j + 1, v[chain[i][j]]);
}
}
}
int main()
{
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
//freopen("in", "r", stdin);
scanf("%i %i", &n, &m);
for (int i = 1; i <= n; ++ i)
scanf("%i", &v[i]);
for (int i = 1; i < n; ++ i)
{
scanf("%i %i", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1, 0);
build_decomp();
for (; m; -- m)
{
scanf("%i %i %i", &t, &x, &y);
if (t == 0)
{
v[x] = y;
update(1, 1, chainsize[chainindex[x]], chainstart[chainindex[x]], chainpos[x], y);
}else
{
int ans = 0;
while (1)
{
if (chainindex[x] == chainindex[y])
{
if (chainpos[x] > chainpos[y]) swap(x, y);
ans = max(ans, query(1, 1, chainsize[chainindex[x]], chainstart[chainindex[x]], chainpos[x], chainpos[y]));
break;
}
if (level[chainfather[chainindex[x]]] < level[chainfather[chainindex[y]]])
swap(x, y);
ans = max(ans, query(1, 1, chainsize[chainindex[x]], chainstart[chainindex[x]], 1, chainpos[x]));
x = chainfather[chainindex[x]];
}
printf("%d\n", ans);
}
}
}