/// Preset de infoarena
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int maxN = 100005;
int n, q;
int val[maxN], sz[maxN], lant[maxN], nrp, pozlant[maxN], p[maxN];
int depth[maxN], euler[2 * maxN], poz_euler[maxN], ind_euler, log2[2 * maxN], rmq[20][2 * maxN];
vector <int> path[maxN], aint[maxN];
vector <int> G[maxN];
void dfs(int nod, int tata)
{
int nxt = 0;
sz[nod] = 1;
euler[++ind_euler] = nod;
poz_euler[nod] = ind_euler;
depth[nod] = depth[tata] + 1;
p[nod] = tata;
for(int vecin : G[nod])
{
if(vecin == tata)
continue;
dfs(vecin, nod);
sz[nod] += sz[vecin];
if(sz[vecin] > sz[nxt])
nxt = vecin;
euler[++ind_euler] = nod;
}
if(sz[nod] == 1)
lant[nod] = ++nrp;
else
lant[nod] = lant[nxt];
path[lant[nod]].push_back(nod);
pozlant[nod] = path[lant[nod]].size();
}
bool cmp(int a, int b)
{
return (depth[a] < depth[b]);
}
int get_lca(int x, int y)
{
int st, dr, log;
st = poz_euler[x];
dr = poz_euler[y];
if(st > dr)
swap(st, dr);
log = log2[dr - st + 1];
int aux = min(rmq[log][st], rmq[log][dr - (1 << log) + 1], cmp);
return aux;
}
void init_aint(int ind, int nod, int st, int dr)
{
if(st == dr)
{
aint[ind][nod] = val[path[ind][st - 1]];
return;
}
int med = (st + dr) / 2;
init_aint(ind, 2 * nod, st, med);
init_aint(ind, 2 * nod + 1, med + 1, dr);
aint[ind][nod] = max(aint[ind][2 * nod], aint[ind][2 * nod + 1]);
}
void update(int ind, int nod, int st, int dr, int poz, int val)
{
if(st == dr)
{
aint[ind][nod] = val;
return;
}
int med = (st + dr) / 2;
if(poz <= med)
update(ind, 2 * nod, st, med, poz, val);
if(med + 1 <= poz)
update(ind, 2 * nod + 1, med + 1, dr, poz, val);
aint[ind][nod] = max(aint[ind][2 * nod], aint[ind][2 * nod + 1]);
}
int query(int ind, int nod, int st, int dr, int qst, int qdr)
{
if(qst <= st && dr <= qdr)
return aint[ind][nod];
int med = (st + dr) / 2, aux = -1;
if(qst <= med)
aux = max(aux, query(ind, 2 * nod, st, med, qst, qdr));
if(med + 1 <= qdr)
aux = max(aux, query(ind, 2 * nod + 1, med + 1, dr, qst, qdr));
return aux;
}
int get_ans(int x, int y)
{
if(depth[x] < depth[y])
swap(x, y);
int aux = -1;
while(lant[x] != lant[y])
{
aux = max(aux, query(lant[x], 1, 1, path[lant[x]].size(), pozlant[x], path[lant[x]].size()));
x = p[path[lant[x]].back()];
}
aux = max(aux, query(lant[x], 1, 1, path[lant[x]].size(), pozlant[x], pozlant[y]));
return aux;
}
int main()
{
fin >> n >> q;
for(int i = 1; i <= n; i++)
fin >> val[i];
for(int i = 1; i < n; i++)
{
int x, y;
fin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1, 0);
depth[0] = 0x3f3f3f3f;
for(int i = 2; i <= ind_euler; i++)
log2[i] = log2[i / 2] + 1;
for(int i = 1; i <= ind_euler; i++)
rmq[0][i] = euler[i];
for(int j = 1; (1 << j) <= ind_euler; j++)
for(int i = 1; i + (1 << (j - 1)) - 1 <= ind_euler; i++)
rmq[j][i] = min(rmq[j - 1][i], rmq[j - 1][i + (1 << (j - 1))], cmp);
for(int i = 1; i <= nrp; i++)
{
aint[i].resize(4 * (path[i].size() + 1));
init_aint(i, 1, 1, path[i].size());
}
for(int i = 1; i <= q; i++)
{
int op, x, y;
fin >> op >> x >> y;
if(op == 0)
update(lant[x], 1, 1, path[lant[x]].size(), pozlant[x], y);
if(op == 1)
{
int ans, lca = get_lca(x, y);
ans = max(get_ans(x, lca), get_ans(y, lca));
fout << ans << '\n';
}
}
return 0;
}