#include <fstream>
#include <vector>
using namespace std;
const int MAXN = 100005;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
vector<int> vecini[MAXN];
int v[MAXN];
int nivel[MAXN];
int n;
struct arborelant
{
vector<int> vallant;
void actualizare(int nod, int st, int dr, int poz, int val)
{
if (st == dr)
{
vallant[nod] = val;
return;
}
int mij = (st + dr) / 2;
if (poz <= mij)
actualizare(2 * nod, st, mij, poz, val);
else actualizare(2 * nod + 1, mij + 1, dr, poz, val);
vallant[nod] = max(vallant[2 * nod], vallant[2 * nod + 1]);
}
int interogare(int nod, int st, int dr, int x, int y)
{
if (st == x && dr == y)
return vallant[nod];
int mij = (st + dr) / 2;
if (y <= mij)
return interogare(2 * nod, st, mij, x, y);
if (x > mij)
return interogare(2 * nod + 1, mij + 1, dr, x, y);
return max(interogare(2 * nod, st, mij, x, mij),
interogare(2 * nod + 1, mij + 1, dr, mij + 1, y));
}
};
void citire(int &m)
{
in >> n >> m;
for (int i = 1;i <= n;++i)
in >> v[i];
for (int i = 1;i < n;++i)
{
int x,y;
in >> x >> y;
vecini[x].push_back(y);
vecini[y].push_back(x);
}
}
int nrsubarbore[MAXN];
int nrlanturi;
vector<int> lant[MAXN];
int idlant[MAXN];
int pozlant[MAXN];
int tatalant[MAXN];
void dfs(int nod, int tata)
{
int fiu_cu_subarbore_maxim = 0;
nrsubarbore[nod] = 1;
for (unsigned int i = 0;i < vecini[nod].size();++i)
{
int vecin = vecini[nod][i];
if (vecin == tata)
continue;
nivel[vecin] = nivel[nod] + 1;
dfs(vecin, nod);
nrsubarbore[nod] += nrsubarbore[vecin];
if(nrsubarbore[vecin] > nrsubarbore[fiu_cu_subarbore_maxim])
fiu_cu_subarbore_maxim = vecin;
}
if (fiu_cu_subarbore_maxim == 0)//frunza
{
++nrlanturi;
idlant[nod] = nrlanturi;
lant[nrlanturi].push_back(nod);
pozlant[nod] = 1;
return;
}
idlant[nod] = idlant[fiu_cu_subarbore_maxim];
pozlant[nod] = pozlant[fiu_cu_subarbore_maxim] + 1;
lant[idlant[nod]].push_back(nod);
for (unsigned int i = 0;i < vecini[nod].size();++i)
{
int vecin = vecini[nod][i];
if(vecin == tata || vecin == fiu_cu_subarbore_maxim)
continue;
tatalant[idlant[vecin]] = nod;
}
}
arborelant alant[MAXN];
void construire_arbori()
{
for (int i = 1;i <= nrlanturi;++i)
{
int llant = lant[i].size();
alant[i].vallant.resize(4 * llant + 2);
for (int j = 0;j < llant;++j)
alant[i].actualizare(1, 1, llant, j + 1, v[lant[i][j]]);
}
}
int main()
{
int m;
citire(m);
//construire lanturi
nivel[1] = 1;
dfs(1,0);
construire_arbori();
while(m > 0)
{
int t,x,y;
in >> t >> x >> y;
if (t == 0)//actualizare
alant[idlant[x]].actualizare(1, 1, lant[idlant[x]].size(), pozlant[x], y);
else//interogare
{
int rasp = -1;
while(idlant[x] != idlant[y])
{
if(nivel[tatalant[idlant[x]]] < nivel[tatalant[idlant[y]]])
swap(x,y);
int nr = alant[idlant[x]].interogare(1, 1, lant[idlant[x]].size(), pozlant[x], lant[idlant[x]].size());
if (nr > rasp)
rasp = nr;
x = tatalant[idlant[x]];
}
int nr = alant[idlant[x]].interogare(1, 1, lant[idlant[x]].size(), min(pozlant[x], pozlant[y]), max(pozlant[x], pozlant[y]));
if (nr > rasp)
rasp = nr;
out << rasp << '\n';
}
--m;
}
return 0;
}