#include <fstream>
#include <vector>
using namespace std;
ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");
const int N = 1e5;
int a[N + 1], siz[N + 1], heavy_son[N + 1], head[N + 1], t[N + 1], l[N + 1], chain[N + 1], h[N + 1], dad[N + 1];
vector <int> g[N + 1];
int n, m, x, y, cer, lant, timp;
void dfs (int node, int tata)
{
siz[node] = 1;
h[node] = h[tata] + 1;
dad[node] = tata;
for (auto it : g[node])
if (it != tata)
{
dfs (it, node);
siz[node] += siz[it];
if (siz[it] > siz[heavy_son[node]])
heavy_son[node] = it;
}
}
void dfs_first (int node, int tata)
{
++timp;
t[timp] = node;
l[node] = timp;
if (heavy_son[tata] != node)
{
head[++lant] = node;
chain[node] = lant;
}
else
{
chain[node] = lant;
}
if (heavy_son[node])
dfs_first (heavy_son[node], node);
for (auto it : g[node])
if (it != tata && it != heavy_son[node])
dfs_first (it, node);
}
struct aint
{
int arb[4 * N + 1];
aint ()
{
for (int i = 1; i <= 4 * N; ++i)
arb[i] = 0;
}
void build (int node, int l, int r)
{
if (l == r)
{
arb[node] = a[t[l]];
return;
}
int med = (l + r) >> 1;
build (node << 1, l, med);
build (node << 1 | 1, med + 1, r);
arb[node] = max (arb[node << 1], arb[node << 1 | 1]);
}
void update (int node, int l, int r, int poz, int val)
{
if (l == r)
{
arb[node] = val;
return;
}
int med = (l + r) >> 1;
if (poz <= med)
update (node << 1, l, med, poz, val);
else
update (node << 1 | 1, med + 1, r, poz, val);
arb[node] = max (arb[node << 1], arb[node << 1 | 1]);
}
int query (int node, int l, int r, int st, int dr)
{
if (l >= st && r <= dr)
return arb[node];
int med = (l + r) >> 1;
int a1, a2;
a1 = a2 = 0;
if (st <= med)
a1 = query (node << 1, l, med, st, dr);
if (dr > med)
a2 = query (node << 1 | 1, med + 1, r, st, dr);
return max (a1, a2);
}
} v;
int solve(int x, int y)
{
int ans = 0;
while (chain[x] != chain[y])
{
int headx = head[chain[x]];
int heady = head[chain[y]];
if (h[headx] > h[heady])
{
ans = max (ans, v.query(1, 1, n, l[headx], l[x]));
x = dad[headx];
}
else
{
ans = max (ans, v.query(1, 1, n, l[heady], l[y]));
y = dad[heady];
}
}
ans = max (ans, v.query (1, 1, n, min (l[x], l[y]), max(l[x], l[y])));
return ans;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> a[i];
for (int i = 1; i < n; ++i)
{
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs (1, 0);
dfs_first(1, 0);
v.build (1, 1, n);
for (int i = 1; i <= m; ++i)
{
cin >> cer >> x >> y;
if (!cer)
{
v.update (1, 1, n, l[x], y);
a[x] = y;
}
else
{
cout << solve(x, y) << '\n';
}
}
return 0;
}