#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
const int Nmax = 1e5 + 5, Lmax = 21;
int v[Nmax], nod[Nmax], blift[Lmax][Nmax], aint[270000];//pt problema
int parent[Nmax], depth[Nmax];//pt arbore
int sus[Nmax], sz[Nmax], lant[Nmax], poz[Nmax]; //pt hld: lant[i] = in ce lant e nodul i, sz[i] = cate lanturi parcurg max in jos de la nodul i, sus[i] = capatul sus al lantului i
vector<int> g[Nmax];
int n, cntlant = 0;
void dfs(int node, int par)//impart nodurile pe lanturi
{
parent[node] = par;
depth[node] = depth[par] + 1;
if (node != 1 && g[node].size() == 1)
{
lant[node] = ++cntlant;
sz[lant[node]] = 1;
return;
}
for (auto it : g[node])
if (it != par)
dfs(it, node);
int maxx = 0, cnt = 0, l = 0;
for (auto it : g[node])
if (it != par)
{
if (sz[lant[it]] > maxx)
maxx = sz[lant[it]], cnt = 1, l = lant[it];
else if (sz[lant[it]] == 1)
cnt++;
}
lant[node] = l;
sz[lant[node]] = maxx;
if (cnt > 1)
sz[lant[node]]++;
}
void dfs2(int node, int par)//aflu cel mai de sus nod al unui lant
{
if (sus[lant[node]] == 0)
sus[lant[node]] = node;
for (auto it : g[node])
if (it != par)
dfs2(it, node);
}
bool cmp(int a, int b)
{
if (sus[lant[a]] != sus[lant[b]])
return sus[lant[a]] < sus[lant[b]];
return depth[a] < depth[b];
}
void binlift()
{
for (int i = 1; i <= n; i++)
blift[0][i] = parent[i];
for (int j = 1; j< Lmax; j++)
for (int i = 1; i <= n; i++)
blift[j][i] = blift[j - 1][blift[j - 1][i]];
}
int getlca(int x, int y)
{
//vreau depth[x] < depth[y] adk x mai sus ca y
if (depth[x] > depth[y]) swap(x, y);
for (int j = Lmax - 1; j >= 0; j--)
if ((depth[y] - depth[x]) & (1 << j))
y = blift[j][y];
if (x == y)
return x;
for (int j = Lmax - 1; j >= 0; j--)
if (blift[j][x] != blift[j][y])
{
x = blift[j][x];
y = blift[j][y];
}
return blift[0][x];
}
void update(int nod, int st, int dr, int poz, int val)
{
if (st > poz || dr < poz)
return;
if (st == dr && dr == poz)
{
aint[nod] = val;
return;
}
int mid = (st + dr) / 2;
update(nod * 2, st, mid, poz, val);
update(nod * 2 + 1, mid + 1, dr, poz, val);
aint[nod] = max(aint[nod * 2], aint[nod * 2 + 1]);
}
int query(int nod, int st, int dr, int qst, int qdr)
{
if (qst > dr || qdr < st)
return 0;
if (qst <= st && dr <= qdr)
return aint[nod];
int mid = (st + dr) / 2;
int l = query(nod * 2, st, mid, qst, qdr), r = query(nod * 2 + 1, mid + 1, dr, qst, qdr);
return max(l, r);
}
int solve(int x, int y)
{
int lca = getlca(x, y), ans = 0;
//cout << x << " " << y << " " << lca << '\n';
while (sus[lant[x]] != sus[lant[lca]])
{
ans = max(ans, query(1, 1, n, poz[sus[lant[x]]], poz[x]));
x = sus[lant[x]];
x = parent[x];
}
ans = max(ans, query(1, 1, n, min(poz[lca], poz[x]), max(poz[lca], poz[x])));
while (sus[lant[y]] != sus[lant[lca]])
{
ans = max(ans, query(1, 1, n, poz[sus[lant[y]]], poz[y]));
y = sus[lant[y]];
y = parent[y];
}
ans = max(ans, query(1, 1, n, min(poz[lca], poz[y]), max(poz[lca], poz[y])));
return ans;
}
int main()
{
int x, y, q, tip;
cin >> n >> q;
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);
dfs2(1, 0);
binlift();
/*for (int i = 1; i <= n; i++)
cout << i << " " << lant[i] << '\n';
cout << '\n';
for (int i = 1; i <= cntlant; i++)
cout << i << ": " << sus[i] << '\n';*/
for (int i = 1; i <= n; i++)
nod[i] = i;
sort(nod + 1, nod + n + 1, cmp);
//for (int i = 1; i <= n; i++)
//cout << a[i] << " ";
for (int i = 1; i <= n; i++)
poz[nod[i]] = i;
for (int i = 1; i <= n; i++)
update(1, 1, n, poz[i], v[i]);
while (q--)
{
cin >> tip >> x >> y;
if (tip == 0)
{
//nodul x devine y
update(1, 1, n, poz[x], y);
}
else
{
cout << solve(x, y) << '\n';
}
}
return 0;
}