#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int MAX_N = 100000;
struct Chain {
int head;
int dad;
int dadDepth;
Chain() {
head = 1;
dad = 0;
dadDepth = 0;
}
};
int n;
int a[1 + MAX_N];
vector<int> g[1 + MAX_N];
bool viz[1 + MAX_N];
int treeSize[1 + MAX_N];
vector<int> heavyPath;
int heavySon[1 + MAX_N];
int posHeavyPath[1 + MAX_N];
int chainCount = 1;
int chainId[1 + MAX_N];
Chain chain[1 + MAX_N];
int arbint[1 + 4 * MAX_N];
void update(int nod, int poz, int val, int st, int dr) {
if(st == dr) {
arbint[nod] = val;
return ;
}
int mij = (st + dr) / 2;
if(poz <= mij)
update(nod * 2, poz, val, st, mij);
else
update(nod * 2 + 1, poz, val, mij + 1, dr);
arbint[nod] = max(arbint[nod * 2], arbint[nod * 2 + 1]);
}
int query(int nod, int a, int b, int st, int dr) {
if(a <= st && dr <= b)
return arbint[nod];
int sol1 = 0, sol2 = 0;
int mij = (st + dr) / 2;
if(a <= mij)
sol1 = query(nod * 2, a, b, st, mij);
if(mij < b)
sol2 = query(nod * 2 + 1, a, b, mij + 1, dr);
return max(sol1, sol2);
}
void dfsSize(int v) {
viz[v] = true;
treeSize[v] = 1;
for (auto u : g[v]) {
if (!viz[u]) {
dfsSize(u);
treeSize[v] += treeSize[u];
if (treeSize[heavySon[v]] < treeSize[u])
heavySon[v] = u;
}
}
}
void dfsHeavy(int v, int depth) {
if (v == 7) {
v++;
v--;
}
viz[v] = true;
heavyPath.push_back(v);
posHeavyPath[v] = (int)heavyPath.size();
chainId[v] = chainCount;
if (heavySon[v] != 0) {
dfsHeavy(heavySon[v], depth + 1);
for (auto u : g[v]) {
if (!viz[u] && u != heavySon[v]) {
chainCount++;
chain[chainCount].head = u;
chain[chainCount].dad = v;
chain[chainCount].dadDepth= depth;
dfsHeavy(u, depth + 1);
}
}
}
}
int pathMax(int u, int v) {
if (chainId[u] == chainId[v])
return query(1, min(posHeavyPath[u], posHeavyPath[v]), max(posHeavyPath[u], posHeavyPath[v]), 1, n);
else {
if (chain[chainId[u]].dadDepth < chain[chainId[v]].dadDepth)
swap(u, v);
int tempAns = query(1, posHeavyPath[chain[chainId[u]].head], posHeavyPath[u], 1, n);
return max(tempAns, pathMax(chain[chainId[u]].dad, v));
}
}
int main() {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
int m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n - 1; i++) {
int v, u;
scanf("%d%d", &v, &u);
g[v].push_back(u);
g[u].push_back(v);
}
dfsSize(1);
for (int i = 1; i <= n; i++)
viz[i] = false;
dfsHeavy(1, 1);
int pos = 0;
for (auto it : heavyPath)
update(1, ++pos, a[it], 1, n);
for (int i = 1; i <= m; i++) {
int t, x, y;
scanf("%d%d%d", &t, &x, &y);
if (t == 0)
update(1, posHeavyPath[x], y, 1, n);
else
printf("%d\n", pathMax(x, y));
}
return 0;
}