#include <cstdio>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctype.h>
#include <cstring>
#include <ctime>
using namespace std;
#define MAXN 100005
int N, M, t, x, y;
int val[MAXN];
vector<int> A[MAXN];
int T[MAXN];
int lvl[MAXN];
int *Aint[MAXN];
bool viz[MAXN];
vector<int> lant[MAXN];
int nrLant;
int inLant[MAXN];
int pos[MAXN];
void dfs(int node, int prev) {
viz[node] = true;
T[node] = prev;
lvl[node] = lvl[prev] + 1;
int maxLen = 0;
int pmax = -1;
for(vector<int> :: iterator it = A[node].begin(); it != A[node].end(); it++)
if(!viz[*it]) {
dfs(*it, node);
if((int)lant[inLant[*it]].size() > maxLen) {
maxLen = (int)lant[inLant[*it]].size();
pmax = *it;
}
}
if(maxLen == 0) {
inLant[node] = nrLant;
lant[nrLant].push_back(node);
nrLant++;
}
else {
int Lmax = inLant[pmax];
inLant[node] = Lmax;
lant[Lmax].push_back(node);
}
}
inline int tataLant(int nod) {
return T[lant[inLant[nod]][0]];
}
void init(int idxLant, int k, int st, int dr) {
if(st == dr) {
Aint[idxLant][k] = val[lant[idxLant][st - 1]];
return;
}
int m = (st + dr) / 2;
init(idxLant, 2 * k, st, m);
init(idxLant, 2 * k + 1, m + 1, dr);
Aint[idxLant][k] = max(Aint[idxLant][2 * k], Aint[idxLant][2 * k + 1]);
}
void update(int idxLant, int k, int st, int dr, int qpos) {
if(st == dr) {
Aint[idxLant][k] = y;
return;
}
int m = (st + dr) / 2;
if(qpos <= m)
update(idxLant, 2 * k, st, m, qpos);
else
update(idxLant, 2 * k + 1, m + 1, dr, qpos);
Aint[idxLant][k] = max(Aint[idxLant][2 * k], Aint[idxLant][2 * k + 1]);
}
int query(int idxLant, int k, int st, int dr, int qst, int qdr) {
if(qst <= st && dr <= qdr) {
return Aint[idxLant][k];
}
int m = (st + dr) / 2;
int ret = 0;
if(qst <= m)
ret = max(ret, query(idxLant, 2 * k, st, m, qst, qdr));
if(qdr > m)
ret = max(ret, query(idxLant, 2 * k + 1, m + 1, dr, qst, qdr));
return ret;
}
int main() {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out","w", stdout);
scanf("%d %d", &N, &M);
for(int i = 1; i <= N; i++)
scanf("%d", &val[i]);
for(int i = 0; i < N - 1; i++) {
scanf("%d %d", &x, &y);
A[x].push_back(y);
A[y].push_back(x);
}
lvl[0] = 0;
dfs(1, 0);
for(int i = 0; i < nrLant; i++) {
reverse(lant[i].begin(), lant[i].end());
Aint[i] = new int[4 * (int)lant[i].size()];
init(i, 1, 1, (int)lant[i].size());
for(vector<int> :: iterator it = lant[i].begin(); it != lant[i].end(); it++)
pos[*it] = (it - lant[i].begin()) + 1;
}
for(int i = 0; i < M; i++) {
scanf("%d %d %d", &t, &x, &y);
if(t == 1) {
int ans = 0;
while(true) {
if(inLant[x] == inLant[y]) {
int left = min(pos[x], pos[y]);
int right = max(pos[x], pos[y]);
ans = max(ans, query(inLant[x], 1, 1, lant[inLant[x]].size(), left, right));
break;
}
if(lvl[tataLant(x)] < lvl[tataLant(y)])
swap(x, y);
ans = max(ans, query(inLant[x], 1, 1, lant[inLant[x]].size(), 1, pos[x]));
x = tataLant(x);
}
printf("%d\n", ans);
}
else {
int crtL = inLant[x];
update(crtL, 1, 1, lant[crtL].size(), pos[x]);
}
}
return 0;
}