#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int nmax = 100005;
vector<int> ls[nmax], comp_lant[nmax];
int nlant;
int a[nmax], x, y, i, j, t, n, m;
int niv[nmax], greu[nmax];
bool viz[nmax];
int dimlant[nmax], carelant[nmax];
int tatalant[nmax], nivlant[nmax];
int arb[nmax], pozlant[nmax];
void dfs(int x) {
bool frunza = 1;
int k = -1;
viz[x] = 1;
greu[x] = 1;
//printf("%d ", x);
for (vector<int>::iterator w = ls[x].begin(); w!=ls[x].end(); w++) {
if (viz[*w]) continue;
frunza = 0;
niv[*w] = niv[x]+1;
dfs(*w);
greu[x] += greu[*w];
if (k == -1) k = *w;
else if (greu[*w] > greu[k]) k = *w;
}
if (frunza) {
carelant[x] = ++nlant;
dimlant[nlant]=1;
comp_lant[nlant].push_back(x);
return;
}
//printf("%d")
carelant[x] = carelant[k];
dimlant[carelant[x]]++;
comp_lant[carelant[x]].push_back(x);
for (vector<int>::iterator w = ls[x].begin(); w!=ls[x].end(); w++) {
if (niv[*w] < niv[x] || *w == k) continue;
tatalant[ carelant[*w] ] = x;
nivlant[ carelant[*w] ] = niv[x];
}
}
void build(int cod, int st, int dr, int decalaj, int lant) {
if (st == dr) {
arb[cod+decalaj] = a[ comp_lant[lant][st-1] ];
return;
}
int mij = (st+dr)/2;
build(2*cod, st, mij, decalaj, lant);
build(2*cod+1, mij+1, dr, decalaj, lant);
arb[cod+decalaj] = max(arb[2*cod + decalaj], arb[2*cod+1 + decalaj]);
}
int gx, val;
void update(int cod, int st, int dr, int decalaj) {
if (st == dr) {
arb[cod+decalaj] = val;
return;
}
int mij = (st+dr)/2;
if (gx <= mij)
update(2*cod, st, mij, decalaj);
else update(2*cod+1, mij+1, dr, decalaj);
arb[cod+decalaj] = max(arb[2*cod + decalaj], arb[2*cod+1 + decalaj]);
}
int gl, gr;
int query(int cod, int st, int dr, int decalaj) {
if (gl <= st && dr <= gr)
return arb[cod+decalaj];
int mij = (st+dr)/2, max1 = 0;
if (gl <= mij)
max1 = query(2*cod, st, mij, decalaj);
if (mij < gr)
max1 = max(max1, query(2*cod+1, mij+1, dr, decalaj));
return max1;
}
void make_graph() {
niv[1]=1;
dfs(1);
for (i = 1; i <= nlant; i++) {
reverse(comp_lant[i].begin(), comp_lant[i].end());
if (i > 1)
pozlant[i] = pozlant[i-1] + 4 * dimlant[i-1];
build(1, 1, dimlant[i], pozlant[i], i);
}
}
void rezolva(int t, int x, int y) {
if (t == 0) {
int X = carelant[x];
gx = niv[x] - nivlant[X];
val = y;
update(1, 1, dimlant[X], pozlant[X]);
return;
}
int sol = 0;
while (1) {
if (carelant[x] == carelant[y]) {
if (niv[x] > niv[y])
swap(x, y);
int X = carelant[x], Y = carelant[y];
gl = niv[x] - nivlant[X];
gr = niv[y] - nivlant[X];
sol = max(sol, query(1, 1, dimlant[X], pozlant[X]) );
break;
}
if (nivlant[carelant[x]] < nivlant[carelant[y]])
swap(x, y);
int X = carelant[x], Y = carelant[y];
gl = 1;
gr = niv[x] - nivlant[X];
sol = max(sol, query(1, 1, dimlant[X], pozlant[X]) );
x = tatalant[X];
}
printf("%d\n",sol);
}
int main() {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d %d\n", &n, &m);
for (i = 1; i <= n; i++)
scanf("%d ", &a[i]);
for (i = 1; i < n; i++) {
scanf("%d %d\n", &x, &y);
ls[x].push_back(y);
ls[y].push_back(x);
}
make_graph();
for (i = 1; i <= m; i++) {
scanf("%d %d %d\n",&t, &x, &y);
rezolva(t,x,y);
}
return 0;
}