#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int Mn = 1e5 + 6;
const int oo = 2e9 + 10;
int n, m, cnt, it, sol;
int val[Mn], weight[Mn], parent[Mn], depth[Mn], wpath[Mn], wpos[Mn], pathsz[Mn], pathhead[Mn];
char buff[Mn];
vector< int > g[Mn], tree[Mn];
void read(int &num)
{
num = 0;
char sgn = '+';
while (!isdigit(buff[it]))
{
sgn = buff[it];
if (++it == Mn)
fread(buff, 1, Mn, stdin), it = 0;
}
while (isdigit(buff[it]))
{
num = num * 10 + buff[it] - '0';
if (++it == Mn)
fread(buff, 1, Mn, stdin), it = 0;
}
if (sgn == '-')
num *= -1;
}
void dfs(int x)
{
weight[x] = 1;
for (auto node : g[x])
if (!weight[node])
{
parent[node] = x;
depth[node] = depth[x] + 1;
dfs(node);
weight[x] += weight[node];
}
}
void hld(int x,int id)
{
wpath[x] = id;
wpos[x] = ++pathsz[id];
int mx = 0;
for (auto node : g[x])
if (node != parent[x] && weight[node] > weight[mx])
mx = node;
if (!mx)
return;
hld(mx, id);
for (auto node : g[x])
if (node != parent[x] && node != mx)
{
pathhead[++cnt] = x;
hld(node, cnt);
}
}
void update(int node, int l, int r, int id, int value)
{
if (l == r)
{
tree[wpath[id]][node] = value;
return;
}
int m = (l + r) / 2;
if (wpos[id] <= m)
update(2 * node, l, m, id, value);
else
update(2 * node + 1, m + 1, r, id, value);
tree[wpath[id]][node] = max(tree[wpath[id]][2 * node], tree[wpath[id]][2 * node + 1]);
}
void query(int node, int l, int r, int fi, int la, int id)
{
if (fi <= l && r <= la)
{
sol = max(sol, tree[wpath[id]][node]);
return;
}
int m = (l + r) / 2;
if (fi <= m)
query(2 * node, l, m, fi, la, id);
if (m < la)
query(2 * node + 1, m + 1, r, fi, la, id);
}
int main()
{
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
read(n); read(m);
for (int i = 1; i <= n; i++)
read(val[i]);
for (int i = 1; i < n; i++)
{
int a, b;
read(a); read(b);
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1);
hld(1, ++cnt);
for (int i = 1; i <= cnt; i++)
tree[i].resize(pathsz[i] * 4);
for (int i = 1; i <= n; i++)
update(1, 1, pathsz[wpath[i]], i, val[i]);
for (; m; m--)
{
int t, x, y;
read(t); read(x); read(y);
if (t == 0)
update(1, 1, pathsz[wpath[x]], x, y);
else
{
int ans = 0;
while (wpath[x] != wpath[y])
{
if (depth[pathhead[wpath[x]]] < depth[pathhead[wpath[y]]])
swap(x, y);
sol = 0;
query(1, 1, pathsz[wpath[x]], 1, wpos[x], x);
ans = max(ans, sol);
x = pathhead[wpath[x]];
}
if (wpos[x] > wpos[y])
swap(x, y);
sol = 0;
query(1, 1, pathsz[wpath[x]], wpos[x], wpos[y], x);
ans = max(ans, sol);
printf("%d\n", ans);
}
}
return 0;
}