#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
const int DIM = 100000, DIMP = 262144;
int n, q, k;
int nodes[DIM + 1], vali[DIM + 1], heavy_head[DIM + 1], heavy_vec[DIM + 1];
int cnt[DIM + 1], niv[DIM + 1], t[DIM + 1], pos[DIM + 1];
vector <int> v[DIM + 1];
struct AINT
{
int v[DIMP + 1];
int pos, val;
int posl, posr, sol;
void build (int nod, int l, int r)
{
if (l == r)
v[nod] = vali[nodes[l]];
else
{
int mid = (l + r) / 2;
build (2 * nod, l, mid);
build (2 * nod + 1, mid + 1, r);
v[nod] = max (v[2 * nod], v[2 * nod + 1]);
}
}
void update (int nod, int l, int r)
{
if (l == r)
v[nod] = val;
else
{
int mid = (l + r) / 2;
if (pos <= mid)
update (2 * nod, l, mid);
if (pos > mid)
update (2 * nod + 1, mid + 1, r);
v[nod] = max (v[2 * nod], v[2 * nod + 1]);
}
}
void query (int nod, int l, int r)
{
if (l >= posl && r <= posr)
sol = max (sol, v[nod]);
else
{
int mid = (l + r) / 2;
if (posl <= mid)
query (2 * nod, l, mid);
if (posr > mid)
query (2 * nod + 1, mid + 1, r);
}
}
void prep_update (int pos, int val)
{
this -> pos = pos;
this -> val = val;
update (1, 1, n);
}
int prep_query (int posl, int posr)
{
this -> posl = posl;
this -> posr = posr;
this -> sol = 0;
query (1, 1, n);
return sol;
}
};
AINT aint;
void read ()
{
int x, y;
fin >> n >> q;
for (int i = 1; i <= n; i++)
fin >> vali[i];
for (int i = 1; i < n; i++)
{
fin >> x >> y;
v[x].push_back (y);
v[y].push_back (x);
}
}
void dfs1 (int nod, int tt, int p)
{
niv[nod] = p;
t[nod] = tt;
cnt[nod] = 1;
for (int i = 0; i < (int) v[nod].size (); i++)
{
int vecin = v[nod][i];
if (vecin != tt)
{
dfs1 (vecin, nod, p + 1);
if (cnt[vecin] > cnt[heavy_vec[nod]])
heavy_vec[nod] = vecin;
cnt[nod] += cnt[vecin];
}
else
{
v[nod][i] = v[nod].back ();
v[nod].pop_back ();
i--;
}
}
}
void dfs2 (int nod)
{
k++;
pos[nod] = k;
nodes[k] = nod;
if (heavy_vec[nod])
{
heavy_head[heavy_vec[nod]] = heavy_head[nod];
dfs2 (heavy_vec[nod]);
}
for (int i = 0; i < (int) v[nod].size (); i++)
{
int vecin = v[nod][i];
if (vecin != heavy_vec[nod])
{
heavy_head[vecin] = vecin;
dfs2 (vecin);
}
}
}
int solve (int x, int y)
{
int sol = 0;
while (heavy_head[x] != heavy_head[y])
{
if (niv[heavy_head[x]] > niv[heavy_head[y]])
{
sol = max (sol, aint.prep_query (pos[heavy_head[x]], pos[x]));
x = t[heavy_head[x]];
}
else
{
sol = max (sol, aint.prep_query (pos[heavy_head[y]], pos[y]));
y = t[heavy_head[y]];
}
}
if (pos[x] <= pos[y])
sol = max (sol, aint.prep_query (pos[x], pos[y]));
else
sol = max (sol, aint.prep_query (pos[y], pos[x]));
return sol;
}
void solve_qry ()
{
int ch, x, y;
while (q--)
{
fin >> ch >> x >> y;
if (ch == 0)
aint.prep_update (pos[x], y);
else
fout << solve (x, y) << "\n";
}
}
int main ()
{
read ();
dfs1 (1, 0, 1);
heavy_head[1] = 1;
dfs2 (1);
aint.build (1, 1, n);
solve_qry ();
return 0;
}