#include <fstream>
#include <vector>
using namespace std;
ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");
const int N = 1e5;
int v[N + 1], sub[N + 1], heavy_son[N + 1], t[N + 1], inv_time[N + 1], dad_lant[N + 1], dad[N + 1], lantul[N + 1], dist[N + 1];
vector <int> g[N + 1];
int n, m, cer, x, y, timp, lant;
void dfs (int node, int tata)
{
sub[node] = 1;
dist[node] = dist[tata] + 1;
dad[node] = tata;
for (auto it : g[node])
if (it != tata)
{
dfs (it, node);
sub[node] += sub[it];
if (sub[heavy_son[node]] < sub[it])
heavy_son[node] = it;
}
}
void dfs_first (int node, int tata)
{
++timp;
t[node] = timp;
inv_time[timp] = node;
if (heavy_son[tata] != node)
{
++lant;
lantul[node] = lant;
dad_lant[lant] = node;
}
else
lantul[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] = v[inv_time[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 rez1, rez2;
rez1 = rez2 = 0;
if (st <= med) rez1 = query (node << 1, l, med, st, dr);
if (dr > med) rez2 = query (node << 1 | 1, med + 1, r, st, dr);
return max (rez1, rez2);
}
} l;
int query (int x, int y)
{
int ans = 0;
while (lantul[x] != lantul[y])
{
int dadx = dad_lant[lantul[x]];
int dady = dad_lant[lantul[y]];
if (dist[dadx] < dist[dady])
{
ans = max (ans, l.query(1, 1, n, t[dady], t[y]));
y = dad[dady];
}
else
{
ans = max (ans, l.query(1, 1, n, t[dadx], t[x]));
x = dad[dadx];
}
}
ans = max (ans, l.query(1, 1, n, min (t[x], t[y]), max(t[x], t[y])));
return ans;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> v[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);
l.build(1, 1, n);
for (int i = 1; i <= m; ++i)
{
cin >> cer >> x >> y;
if (!cer)
{
l.update (1, 1, n, t[x], y);
v[x] = y;
}
else
{
cout << query (x, y) << '\n';
}
}
return 0;
}