#include <fstream>
#include <queue>
#include <algorithm>
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
vector <vector <int> > g, p;
vector <int> v, lv, nod, tata, loc, gap, arb;
vector <bool> viz, done;
int n, m, tp = 1;
void update (int nod, int lo, int hi, int pos, int val, int gap) {
if (lo == hi) {
arb[nod+gap] = val;
return;
}
int mid = (lo + hi) >> 1;
if (pos <= mid)
update (nod << 1, lo, mid, pos, val, gap);
else
update ((nod << 1) + 1, mid+1, hi, pos, val, gap);
arb[nod+gap] = max (arb[(nod << 1) + gap], arb[(nod << 1) + 1 + gap]);
}
int query (int nod, int lo, int hi, int qlo, int qhi, int gap) {
if (qlo <= lo && hi <= qhi)
return arb[nod+gap];
int mid = (lo + hi) >> 1, res = 0;
if (qlo <= mid)
res = max(res, query (nod << 1, lo, mid, qlo, qhi, gap));
if (qhi > mid)
res = max(res, query ((nod << 1) + 1, mid + 1, hi, qlo, qhi, gap));
return res;
}
bool cmp(int a, int b) {
return nod[a] > nod[b];
}
void Resize() {
viz.resize(n+1); done.resize(n+1);
g.resize(n+1); p.resize(n+1);
v.resize(n+1); lv.resize(n+1); nod.resize(n+1);
tata.resize(n+1); loc.resize(n+1); gap.resize(n+1);
arb.resize(4*(n+2));
}
void dfs(int x, int val) {
viz[x] = 1;
nod[x]++;
lv[x] = val;
for (vector <int> :: iterator it = g[x].begin(); it != g[x].end(); ++it)
if (!viz[*it]) {
dfs(*it, val + 1);
nod[x] += nod[*it];
}
}
void Heavy_Path (int x, int path) {
viz[x] = 0;
loc[x] = path;
p[path].push_back(x);
for (vector <int> :: iterator it = g[x].begin(); it != g[x].end(); ++it)
if (viz[*it]) {
if (!done[x]) {
done[x] = 1;
Heavy_Path(*it, path);
}
else {
tata[++tp] = x;
Heavy_Path(*it, tp);
}
}
}
int main() {
fin >> n >> m;
Resize();
for (int i = 1; i <= n; ++i)
fin >> v[i];
for (int i = 1; i < n; ++i) {
int x, y;
fin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1, 1);
for (int i = 1; i <= n; ++i)
sort(g[i].begin(), g[i].end(), cmp);
Heavy_Path(1, 1);
for (int i = 1; i <= tp; ++i) {
gap[i] = gap[i-1] + p[i-1].size() * 4;
for (vector <int> :: iterator it = p[i].begin(); it != p[i].end(); ++it)
update (1, 1, p[i].size(), lv[*it] - lv[tata[loc[*it]]], v[*it], gap[i]);
}
while (m--) {
bool t;
int x, y;
fin >> t >> x >> y;
if (!t)
update (1, 1, p[loc[x]].size(), lv[x] - lv[tata[loc[x]]], y, gap[loc[x]]);
else {
int sol = 0;
while (loc[x] != loc[y]) {
if (lv[tata[loc[x]]] < lv[tata[loc[y]]])
swap(x,y);
sol = max (sol, query(1, 1, p[loc[x]].size(), 1, lv[x] - lv[tata[loc[x]]], gap[loc[x]]));
x = tata[loc[x]];
}
if (lv[x] < lv[y])
swap(x,y);
sol = max (sol, query (1, 1, p[loc[x]].size(), lv[y] - lv[tata[loc[x]]], lv[x] - lv[tata[loc[x]]], gap[loc[x]]));
fout << sol << "\n";
}
}
fcloseall();
}