#include <fstream>
#include <vector>
#include <algorithm>
#define DIM 101000
#define DIM_LOG 2200
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
class Muchie {
public:
int id;
int jos;
int sus;
vector<int> membrii;
int D[DIM_LOG];
void Adauga (int nod, int son);
int Query(int, int, int, int, int); // returneaza maximul pe interval
void Update(int, int, int, int);
void Build(int, int, int);
};
int n, Q;
vector<int> G[DIM]; // graf initial
int v[DIM], t[DIM];
Muchie muchii[DIM_LOG]; // heavypaths
int muc[DIM], nr_muc; // din ce muchie face parte nodul
int item[DIM]; // ce pozitie ocupa i in muchii[muc[i]].membrii
int s[DIM]; // cate noduri are subarborele i
int poz, x, y, j, timp;
int in[DIM], out[DIM]; // timpii de decoperire
vector<bool> f;
void Read();
void DF1(int);
void DF(int);
int Drum(int, int); // returneaza maximul intre x si y
bool Is_ancestor(int, int);
int main()
{
Read();
f.resize(n+1);
DF1(1);
DF(1);
for (int i = 1; i <= nr_muc; ++i)
muchii[i].Build(1, 0, muchii[i].membrii.size() - 1 );
int x, y;
bool k;
for (int i = 1; i <= Q; ++i)
{
fin >> k >> x >> y;
if (k) fout << Drum(x, y) << '\n';
else
{
v[x] = y;
if (muc[x]) muchii[muc[x]].Update(item[x], 1, 0, muchii[muc[x]].membrii.size() - 1);
}
}
fin.close();
fout.close();
return 0;
}
void Read()
{
fin >> n >> Q;
for (int i = 1; i <= n; ++i)
fin >> v[i];
int x, y;
for (int i = 1; i < n; ++i)
{
fin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
}
void DF1(int nod)
{
if (in[nod]) return;
in[nod] = ++timp;
s[nod] = 1;
for (int i = 0; i < G[nod].size(); ++i)
{
int son = G[nod][i];
if (in[son]) continue;
DF1(son);
t[son] = nod;
s[nod] += s[son];
}
out[nod] = ++timp;
}
void DF(int nod)
{
if (f[nod]) return;
f[nod] = 1;
for (int i = 0; i < G[nod].size(); ++i)
{
int son = G[nod][i];
if (f[son]) continue;
if (s[son] >= s[nod] / 2)
{
if (muc[nod]) muchii[muc[nod]].Adauga(nod, son); // il adaug pe son la muchia tatalui
else
{
nr_muc++;
muchii[nr_muc].Adauga(nod, son); // creez alta muchie heavy (nod-son)
}
}
DF(son);
}
}
int Drum(int x, int y)
{
if (x == y) return v[x];
if (Is_ancestor(x,y)) return Drum(y,x);
if (muc[x]) // x este pe un heavy path (3 variante)
{
int capat = muchii[muc[x]].sus;
if (muc[x] == muc[y]) // sunt pe acelasi heavy path
return muchii[muc[x]].Query(item[x], item[y], 1, 0, muchii[muc[x]].membrii.size() - 1);
if (Is_ancestor(y, capat)) // y - e mai sus in arbore decat muc[i].sus
return max(muchii[muc[x]].Query(item[x], item[capat], 1, 0, muchii[muc[x]].membrii.size() - 1), Drum(t[capat], y));
if (Is_ancestor(capat, y)) // y este mai jos decat capat
{
int stramos;
Muchie path = muchii[muc[x]];
int st(0), dr(muchii[muc[x]].membrii.size() - 1);
while (st <= dr)
{
int mij = (st + dr) / 2;
if (Is_ancestor(path.membrii[mij], y))
{
stramos = path.membrii[mij];
dr = mij - 1;
}
else st = mij+1;
} // gasesc stramosul de pe heavy path a lui y care are nivel minim
return max(muchii[muc[x]].Query(item[x], item[stramos], 1, 0, muchii[muc[x]].membrii.size() - 1), Drum(y, stramos));
}
}
return max(v[x], Drum(t[x], y)); // ma duc pe light path
}
bool Is_ancestor(int x, int y)
{
return (in[x] < in[y]) && (out[x] > out[y]);
}
int Muchie::Query(int x, int y, int nod, int st, int dr)
{
if (y < x) swap(x,y);
if (x <= st && y >= dr)
{
return v[membrii[D[nod]]];
}
int mij = (st + dr) / 2;
int aux1(0), aux2(0);
if (x <= mij) aux1 = Query(x, y, 2*nod, st, mij);
if (y > mij) aux2 = Query(x, y, 2*nod+1, mij+1, dr);
return max(aux1, aux2);
}
void Muchie::Adauga(int nod, int son)
{
if (!id) // muchie noua
{
id = nr_muc;
sus = nod;
jos = son;
membrii.push_back(nod);
item[nod] = membrii.size() - 1;
muc[nod] = id;
membrii.push_back(son);
item[son] = membrii.size() - 1;
muc[son] = id;
}
else // nod este deja adaugat
{
jos = son;
membrii.push_back(son);
item[son] = membrii.size() - 1;
muc[son] = id;
}
}
void Muchie::Update(int poz, int nod, int st, int dr)
{
if (st == dr)
{
D[nod] = st;
return;
}
int mij = (st + dr) / 2;
if (poz <= mij) Update(poz, 2*nod, st, mij);
else Update(poz, 2*nod+1, mij+1, dr);
if (v[membrii[D[2*nod]]] > v[membrii[D[2*nod+1]]])
D[nod] = D[2*nod];
else D[nod] = D[2*nod+1];
}
void Muchie::Build(int nod, int st, int dr)
{
if (st == dr)
{
D[nod] = st;
return;
}
int mij = (st + dr) / 2;
Build(2*nod, st, mij);
Build(2*nod+1, mij+1, dr);
if (v[membrii[D[2*nod]]] > v[membrii[D[2*nod+1]]])
D[nod] = D[2*nod];
else D[nod] = D[2*nod+1];
}