#include <bits/stdc++.h>
using namespace std;
ifstream f ("heavypath.in");
ofstream g ("heavypath.out");
constexpr int NMAX = 1e5 + 5;
int N, M;
int V[NMAX];
vector <int> G[NMAX];
int arb[4*NMAX];
void Update_Tree (int nod, int a, int b, int poz, int val) {
if (a == b) {
arb[nod] = val;
return;
}
int mij = (a + b) / 2;
if (poz <= mij) Update_Tree(2*nod, a, mij, poz, val);
else Update_Tree(2*nod+1, mij+1, b, poz, val);
arb[nod] = max(arb[2*nod], arb[2*nod+1]);
}
int Query_Tree (int nod, int a, int b, int qa, int qb) {
if (qa <= a && b <= qb) return arb[nod];
int mij = (a + b) / 2;
int ans_L = 0, ans_R = 0;
if (qa <= mij) ans_L = Query_Tree(2*nod, a, mij, qa, qb);
if (mij < qb) ans_R = Query_Tree(2*nod+1, mij+1, b, qa, qb);
return max(ans_L, ans_R);
}
void Read () {
f >> N >> M;
for (int i = 1; i <= N; ++ i )
f >> V[i];
for (int i = 1; i < N; ++ i ) {
int x, y;
f >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
}
int Max_Son[NMAX];
int Size[NMAX];
int chains;
int ID[NMAX];
int Size_ID[NMAX];
int First[NMAX];
int Level[NMAX];
int Dad[NMAX];
int poz[NMAX];
int cnt = 0;
void Dfs (int node, int dad = -1) {
Max_Son[node] = -1;
Size[node] = 1;
Dad[node] = dad;
for (auto it : G[node]) {
if (it == dad) continue;
Level[it] = Level[node] + 1;
Dfs(it, node);
if (Max_Son[node] == -1 || Size[Max_Son[node]] < Size[it])
Max_Son[node] = it;
Size[node] += Size[it];
}
}
void Split (int node) {
ID[node] = chains;
poz[node] = ++cnt;
Size_ID[chains] ++;
if (Max_Son[node] == -1) return;
Split(Max_Son[node]);
for (auto it : G[node]) {
if (it == Dad[node] || it == Max_Son[node]) continue;
++ chains;
First[chains] = it;
Split(it);
}
}
void HeavyPath () {
Dfs(1);
Split(1);
for (int i = 1; i <= N; ++ i )
Update_Tree(1, 1, N, poz[i], V[i]);
}
void Update (int x, int val) {
Update_Tree(1, 1, N, poz[x], val);
}
int Query (int x, int y) {
if (ID[x] == ID[y])
return Query_Tree(1, 1, N, min(poz[x], poz[y]), max(poz[x], poz[y]));
if (Level[First[ID[x]]] < Level[First[ID[y]]])
swap(x, y);
int ans = Query_Tree(1, 1, N, poz[First[ID[x]]], poz[x]);
return max(ans, Query(Dad[First[ID[x]]], y));
}
void Solve () {
for (int i = 1; i <= M; ++ i ) {
int tip, x, y;
f >> tip >> x >> y;
if (tip == 0) {
Update(x, y);
}
else {
g << Query(x, y) << '\n';
}
}
}
int main () {
Read();
HeavyPath();
Solve();
return 0;
}