using namespace std;
#include <fstream>
#include <vector>
#include <algorithm>
#include <string>
#define Nmax 100001
int p, new_val, a, b;
int v[Nmax], h[Nmax];
int nrL, path[Nmax], p_father[Nmax], pos[Nmax], nr_nodes[Nmax];
vector< int > G[Nmax], aint[Nmax];
int DFS(int);
void update(vector<int>&, int, int, int);
int query(vector<int>&, int, int, int);
int main()
{
int i, n, m, type, x, y, val, val_max;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
fin >> n >> m;
for (i = 1; i <= n; ++i) fin >> v[i];
for (i = 1; i < n; ++i)
{
fin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
h[1] = 1;
DFS(1);
p_father[path[1]] = 0;
for (i = 1; i <= nrL; ++i) aint[i].resize(4 * nr_nodes[i]);
for (i = 1; i <= n; ++i) { p = pos[i]; new_val = v[i]; update(aint[path[i]], 1, 1, nr_nodes[path[i]]); }
for (i = 1; i <= m; ++i)
{
fin >> type >> x >> y;
if (type == 0)
{
p = pos[x];
new_val = y;
update(aint[path[x]], 1, 1, nr_nodes[path[x]]);
}
else
{
val_max = 0;
while (path[x] != path[y])
{
if (h[p_father[path[x]]] > h[p_father[path[y]]]) swap(x, y);
a = pos[y];
b = nr_nodes[path[y]];
val = query(aint[path[y]], 1, 1, nr_nodes[path[y]]);
y = p_father[path[y]];
val_max = max(val_max, val);
}
a = min(pos[x], pos[y]);
b = max(pos[x], pos[y]);
val = query(aint[path[x]], 1, 1, nr_nodes[path[x]]);
val_max = max(val_max, val);
fout << val_max << '\n';
}
}
fin.close();
fout.close();
return 0;
}
int DFS(int vf)
{
int fiu, nr, nrmax, sum;
bool leaf = true;
fiu = 0;
sum = nrmax = 0;
for (auto &to : G[vf])
if(!h[to])
{
h[to] = 1 + h[vf];
nr = DFS(to);
sum += nr;
if (fiu == 0 || nr > nrmax) fiu = to, nrmax = nr;
leaf = false;
}
for (auto &to : G[vf])
if (h[to] == 1 + h[vf] && to != fiu)
p_father[path[to]] = vf;
if (leaf)
{
path[vf] = ++nrL;
pos[vf] = 1;
nr_nodes[nrL] = 1;
}
else
{
path[vf] = path[fiu];
pos[vf] = 1 + pos[fiu];
++nr_nodes[path[vf]];
}
return 1 + sum;
}
void update(vector<int> &aint, int node, int l, int r)
{
if (l == r)
{
aint[node] = new_val;
return;
}
int mid = (l + r) / 2;
if (p <= mid) update(aint, 2 * node, l, mid);
else update(aint, 2 * node + 1, mid + 1, r);
aint[node] = max(aint[2 * node], aint[2 * node + 1]);
}
int query(vector<int>& aint, int node, int l, int r)
{
if (a <= l && r <= b) return aint[node];
int v1 = 0, v2 = 0, mid = (l + r) / 2;
if (a <= mid) v1 = query(aint, 2 * node, l, mid);
if (b > mid) v2 = query(aint, 2 * node + 1, mid + 1, r);
return max(v1, v2);
}