#include <stdio.h>
#include <vector>
#define MAXN 100005
#define MAXLOGN 18
#define MAX(a, b) (((a) > (b))?(a):(b))
using namespace std;
int typeq, x, y;
int n, m, v[MAXN], sz[MAXN], dad[MAXN][MAXLOGN], chainNo[MAXN], chainPoz[MAXN], lvl[MAXN];
int chainCnt = 1, chainHead[MAXN];
vector<int> chain[MAXN], aint[MAXN];
vector<int> G[MAXN];
int lca(int x, int y) {
if(lvl[x] < lvl[y]) swap(x, y);
for(int i = MAXLOGN - 1; i >= 0; i--)
if(lvl[x] - (1 << i) >= lvl[y])
x = dad[x][i];
if(x == y) return x;
for(int i = MAXLOGN - 1; i >= 0; i--)
if(dad[x][i] != dad[y][i]) {
x = dad[x][i];
y = dad[y][i];
}
return dad[x][0];
}
void DFS(int u, int p) {
int x = p;
for(int i = 0; i < MAXLOGN; i++) {
dad[u][i] = x;
x = dad[x][i];
}
lvl[u] = lvl[p] + 1;
sz[u] = 1;
for(auto x: G[u])
if(x != p) {
DFS(x, u);
sz[u] += sz[x];
}
}
void HLD(int u) {
if(chain[chainCnt].size() == 1) chainHead[chainCnt] = u;
chain[chainCnt].push_back(v[u]);
chainNo[u] = chainCnt;
chainPoz[u] = chain[chainCnt].size() - 1;
int heavySon = 0;
for(auto x: G[u])
if(x != dad[u][0] && sz[x] > sz[heavySon])
heavySon = x;
if(!heavySon) return;
HLD(heavySon);
for(auto x: G[u])
if(x != dad[u][0] && x != heavySon) {
chain[++chainCnt].push_back(0);
HLD(x);
}
}
void build_ai(vector<int> &ai, vector<int> &v, int node, int l, int r) {
if(l == r) {
ai[node] = v[l];
return;
}
int mid = (l + r) >> 1;
build_ai(ai, v, 2 * node, l, mid);
build_ai(ai, v, 2 * node + 1, mid + 1, r);
ai[node] = MAX(ai[2 * node], ai[2 * node + 1]);
}
void query_ai(vector<int> &ai, vector<int> &v, int node, int l, int r, int lq, int rq, int &ans) {
if(lq <= l && r <= rq) {
ans = MAX(ans, ai[node]);
return;
}
int mid = (l + r) >> 1;
if(lq <= mid) query_ai(ai, v, 2 * node, l, mid, lq, rq, ans);
if(mid + 1 <= rq) query_ai(ai, v, 2 * node + 1, mid + 1, r, lq, rq, ans);
}
void update_ai(vector<int> &ai, vector<int> &v, int node, int l, int r, int &pos) {
if(l == r) {
ai[node] = v[l];
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) update_ai(ai, v, 2 * node, l, mid, pos);
else update_ai(ai, v, 2 * node + 1, mid + 1, r, pos);
ai[node] = MAX(ai[2 * node], ai[2 * node + 1]);
}
int upSolve(int u, int v) {
int ans = 0;
while(chainNo[u] != chainNo[v]) {
int x = chainNo[u];
query_ai(aint[x], chain[x], 1, 1, chain[x].size() - 1, 1, chainPoz[u], ans);
u = dad[chainHead[x]][0];
}
int x = chainNo[u];
query_ai(aint[x], chain[x], 1, 1, chain[x].size() - 1, chainPoz[v], chainPoz[u], ans);
return ans;
}
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", &v[i]);
for(int i = 1; i < n; i++) {
scanf("%d %d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
DFS(1, 0);
chain[1].push_back(0);
HLD(1);
for(int i = 1; i <= chainCnt; i++) {
aint[i].resize(chain[i].size() * 2);
build_ai(aint[i], chain[i], 1, 1, chain[i].size() - 1);
}
while(m--) {
scanf("%d %d %d", &typeq, &x, &y);
if(typeq) {
int z = lca(x, y);
int val1 = upSolve(x, z), val2 = upSolve(y, z);
printf("%d\n", MAX(val1, val2));
}
else {
int id = chainNo[x], pos = chainPoz[x];
chain[id][pos] = y;
update_ai(aint[id], chain[id], 1, 1, chain[id].size() - 1, pos);
}
}
return 0;
}