#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
const int nmax = 1e5 + 5;
struct ceva{
int dad, w, val, lant, deep, ind;
}v[nmax];
int n, q, aint[4 * nmax], lg[nmax], up[nmax][20], aux[nmax];
vector<int> l, vec[nmax];
bool cmp(int i, int j)
{
if(v[i].lant != v[j].lant)
return v[i].lant < v[j].lant;
return v[i].deep < v[j].deep;
}
void dfs(int nod)
{
int poz = 0, oki = 0, maxx = 0, nr = 0;
for(auto x : vec[nod])
{
if(x == v[nod].dad)
continue;
v[x].dad = nod;
v[x].deep = v[nod].deep + 1;
up[x][0] = nod;
for(int i = 1; i <= lg[v[x].deep]; i ++)
up[x][i] = up[up[x][i - 1]][i - 1];
dfs(x);
oki = 1;
if(maxx < v[x].w)
maxx = v[x].w, nr = 1, poz = x;
else if(maxx == v[x].w)
nr ++;
}
if(!oki)
{
l.push_back(nod);
v[nod].lant = l.size() - 1;
v[nod].w = 1;
return;
}
if(nr > 1)
v[nod].w = maxx + 1;
else
v[nod].w = maxx;
v[nod].lant = v[poz].lant;
l[v[nod].lant] = nod;
}
int lca(int x, int y)
{
if(v[x].deep > v[y].deep)
swap(x, y);
if(v[x].deep != v[y].deep)
{
int nr = v[y].deep - v[x].deep;
for(int i = 0; i < 20; i ++)
if((1<<i)&nr)
y = up[y][i];
}
if(x == y)
return x;
for(int i = 20; i >= 0; i --)
if(up[x][i] != up[y][i])
x = up[x][i], y = up[y][i];
return up[x][0];
}
void update(int nod, int st, int dr, int x, int val)
{
if(st == dr)
aint[nod] = val;
else
{
int mij = (st + dr) / 2;
if(x <= mij)
update(2 * nod, st, mij, x, val);
else
update(2 * nod + 1, mij + 1, dr, x, val);
aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
}
int query(int nod, int st, int dr, int x, int y)
{
if(x <= st && dr <= y)
return aint[nod];
else
{
int mij = (st + dr) / 2, m1 = 0, m2 = 0;
if(x <= mij)
m1 = query(2 * nod, st, mij, x, y);
if(y > mij)
m2 = query(2 * nod + 1, mij + 1, dr, x, y);
return max(m1, m2);
}
}
int solv(int i, int j)
{
if(v[i].lant == v[j].lant)
return query(1, 1, n, v[i].ind, v[j].ind);
int ans = query(1, 1, n, v[l[v[j].lant]].ind, v[j].ind);
j = v[l[v[j].lant]].dad;
return max(ans, solv(i, j));
}
int main()
{
for(int i = 2; i <= nmax - 5; i ++) lg[i] = lg[i / 2] + 1;
f >> n >> q;
for(int i = 1; i <= n; i ++)
{
f >> v[i].val;
aux[i] = i;
}
for(int i = 1; i < n; i ++)
{
int x, y; f >> x >> y;
vec[x].push_back(y);
vec[y].push_back(x);
}
v[1].deep = 1;
dfs(1);
sort(aux + 1, aux + n + 1, cmp);
for(int i = 1; i <= n; i ++)
v[aux[i]].ind = i;
for(int i = 1; i <= n; i ++)
update(1, 1, n, v[i].ind, v[i].val);
for(; q >= 1; q --)
{
int tip, x, y;
f >> tip >> x >> y;
if(tip == 0)
{
update(1, 1, n, v[x].ind, y);
v[x].val = y;
}
else
{
int an = lca(x, y), ans;
if(an == x || an == y)
{
if(an == y)
swap(x, y);
ans = solv(x, y);
}
else
ans = max(solv(an, x), solv(an, y));
g << ans << '\n';
}
}
return 0;
}