#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int lanturi;
vector <int> graf[MAXN];
vector <int> arb[MAXN];
vector <int> hpd[MAXN];
int nivel[MAXN];
int lant[MAXN];
int sub[MAXN];
int tata[MAXN];
int poz[MAXN];
int val[MAXN];
void ArbInit(int node, int st, int dr, int aint){
if (st == dr){
arb[aint][node] = val[hpd[aint][st]];
return;
}
int mij = (st + dr) / 2;
ArbInit(2 * node, st, mij, aint);
ArbInit(2 * node + 1, mij + 1, dr, aint);
arb[aint][node] = max(arb[aint][node * 2], arb[aint][node * 2 + 1]);
}
void HpdInit(int node, int ancest){
tata[node] = ancest;
nivel[node] = nivel[ancest]+1;
sub[node] = 1;
for (auto x:graf[node]){
if(x == ancest)
continue;
HpdInit(x, node);
sub[node] += sub[x];
}
if (sub[node] == 1){
++lanturi;
lant[node] = lanturi;
poz[node] = 0;
hpd[lanturi].push_back(node);
return ;
}
int best = 0;
for(auto x:graf[node]){
if(x == ancest)
continue;
if(sub[x] > sub[best])
best = x;
}
lant[node] = lant[best];
hpd[lant[node]].push_back(node);
poz[node] = int(hpd[lant[node]].size()) - 1;
}
int Query(int node, int st, int dr, int a, int b, int aint){
if (a <= st && dr <= b)
return arb[aint][node];
int mij = (st + dr) / 2;
int maxst = -1, maxdr = -1;
if (a <= mij)
maxst = Query(node * 2, st, mij, a, b, aint);
if (mij < b)
maxdr = Query(node * 2 + 1, mij + 1, dr, a, b, aint);
return max(maxst, maxdr);
}
void Update(int node, int st, int dr, int pozit, int val, int aint){
if (st == dr){
arb[aint][node] = val;
return ;
}
int mij = (st + dr) / 2;
if (pozit <= mij)
Update(node * 2, st, mij, pozit, val, aint);
else
Update(node * 2 + 1, mij + 1, dr, pozit, val, aint);
arb[aint][node] = max(arb[aint][node * 2], arb[aint][node * 2 + 1]);
}
int findMaxim(int x, int y){
int ans = -3;
int lx = lant[x], ly = lant[y];
if (lx == ly){
int a = min(poz[x], poz[y]), b = max(poz[x], poz[y]);
ans = max(ans, Query(1, 0, int(hpd[lx].size()) - 1, a, b, lx));
}
else{
if (nivel[hpd[lx][0]] < nivel[hpd[ly][0]]){
swap(x, y);
swap (lx, ly);
}
ans = max (ans, Query(1, 0, int(hpd[lx].size()) - 1, 0, poz[x], lx));
ans = max (ans, findMaxim(tata[hpd[lx][0]], y));
}
return ans;
}
int main()
{
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
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;
graf[x].push_back(y);
graf[y].push_back(x);
}
HpdInit(1, 0);
for(int i = 1; i <= lanturi; ++i)
reverse(hpd[i].begin(), hpd[i].end());
for(int i = 1; i <= n; ++i)
poz[i] = int(hpd[lant[i]].size()) - 1 - poz[i];
for(int i = 1; i <= lanturi; ++i){
arb[i].resize(int(hpd[i].size()) << 2);
ArbInit(1, 0, int(hpd[i].size()) - 1, i);
}
while(m){
int op, x, y;
fin >> op >> x >> y;
if(op) fout << findMaxim(x, y) << "\n";
else Update(1, 0, int(hpd[lant[x]].size()) - 1, poz[x], y, lant[x]);
m--;
}
return 0;
}