#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 50;
const int INF = 1e8;
const int LOGMAX = 20 + 4;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
vector <int> g[MAXN], l[LOGMAX];
int lant[MAXN], sizee[MAXN], val[MAXN], father[MAXN], poz[MAXN];
bool seen[MAXN];
int aint[LOGMAX][4 * MAXN+ 2], cnt;
///lant[i] - lantul nodului i
///sizee[i] - marimea subarborelui de radacina i
///val[i] - valoarea nodului i
///father[i] - nodul de care se leaga lantul lui i
///poz[i] - pozitia in cadrul arborelui de intervale a lui i
///aint[i][j] - nodul j din arborele de intervale al lantului i
///l[i] - nodurile lantului i
int findd(int node){ ///stabilesc nodul in care se leaga lantul lui 'node' de graf
if(lant[node] != lant[father[node]]) return father[node];
return findd(father[node]);
}
void dfs(int node, int papa){ ///calculez marimea subarborelui fiecaruia
if(!node) return ;
sizee[node] = 1;
for(auto x : g[node]) {
if(x != papa) {
dfs(x, node);
sizee[node] = sizee[x] + 1;
}
}
}
void dfs2(int node){ ///creez lanturile adaugand greedy fiul cu size maxim
if(seen[node]) return ;
seen[node] = true;
l[cnt].push_back(node);
lant[node] = cnt;
int maxim = 0, fiu = 0;
for(auto x : g[node]){
if(sizee[x] > maxim and !seen[x])
maxim = sizee[x], fiu = x;
}
if(fiu ) dfs2(fiu);
}
/// arborii de intervale pe lanturi
void update(int p, int pos, int st, int dr, int l, int valoare){
if(st == dr) {
aint[l][p] = valoare;
return;
}
int m = (st + dr ) / 2;
if(pos > m) update(2 * p + 1, pos, m + 1, dr, l, valoare);
else update(2 * p , pos, st, m, l, valoare);
aint[l][p] = max(aint[l][2 * p], aint[l][2 * p + 1]);
}
int rasp;
void query(int p, int left, int right, int st, int dr, int l){
if(left >= st and right <= dr) {
rasp = max(rasp, aint[l][p]);
return ;
}
int m = (left + right) / 2;
if(dr > m) query(2 * p + 1, m + 1, right, st, dr, l);
if(st <= m) query(2 * p, left, m, st, dr, l);
}
int main() /// HEAVY PATH DECOMPOSITION
{
ios::sync_with_stdio(false);
fin.tie(0); fout.tie(0);
int n, m ; fin >> n >> m;
for(int i = 1; i <= n; ++i)
fin >> val[i];
for(int i = 1; i < n; ++i){
int x, y; fin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
father[y] = x;
}
dfs(1, 0);
for(int i = 1; i <= n; ++i)
if(!seen[i]) ++cnt, dfs2(i);
for(int i = 1; i <= cnt; ++i)
for(int j = 0; j <= l[i].size() - 1; ++j)
poz[l[i][j]] = j + 1;
for(int i = 1; i <= n; ++i){
father[i] = findd(i);
update(1, poz[i], 1, l[lant[i]].size(), lant[i], val[i]);
}
for(int i = 1; i <= m; ++i){
int type, x , y;
fin >> type >> x >> y;
if(type){
rasp = 0;
if(lant[x] == 1) swap(x, y);
while(lant[x] != lant[y]){
query(1, 1, l[lant[x]].size(), 1, poz[x], lant[x]);
x = father[x];
}
query(1, 1, l[lant[x]].size(), min(poz[x], poz[y]), max(poz[y], poz[x]),lant[x]);
fout << rasp << '\n';
}
else update(1, poz[x], 1, l[lant[x]].size(), lant[x], y);
}
return 0;
}