#include <bits/stdc++.h>
using namespace std;
const int N = 100001;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int nodevalue[N],poz[N],level[N],where[N],father[N],weight[N];
vector <int> graph[N];
vector <int> hp[N];
vector <int> arbint[N];
int nrhp;
void arint(int nod, int st, int dr, int pos){
if(st == dr)
{
arbint[pos][nod] = nodevalue[hp[pos][st]];
return;
}
int mijl = (st+dr)>>1;
arint(nod << 1, st, mijl, pos);
arint(nod << 1 | 1, mijl + 1, dr, pos);
arbint[pos][nod] = max(arbint[pos][nod << 1],arbint[pos][nod << 1 | 1]);
}
void update(int node, int st,int dr, int poz, int val, int currentaint){
if(st == dr)
{
arbint[currentaint][node] = val;
return;
}
int mij = (st+dr)>>1;
if(poz <= mij)
update(node << 1, st, mij, poz, val,currentaint);
else
update(node << 1 | 1, mij + 1, dr, poz, val, currentaint);
arbint[currentaint][node] = max(arbint[currentaint][node << 1], arbint[currentaint][node << 1 | 1]);
}
void hpd(int node, int father1){
father[node] = father1;
level[node] = level[father1]+1;
weight[node] = 1;
for(auto x : graph[node])
{
if(x != father1){
hpd(x, node);
weight[node] += weight[x];
}
}
if(weight[node] == 1) {
++nrhp;
where[node] = nrhp;
poz[node] = 0;
hp[nrhp].push_back(node);
return;
}
int good = 0;
for(auto x : graph[node])
{
if(x==father1)continue;
if(weight[x] > weight[good])
good = x;
}
where[node] = where[good];
poz[node] = (int)hp[where[node]].size();
hp[where[node]].push_back(node);
}
int query(int node, int st, int dr, int a, int b, int currentaint){
if(a <= st && b >= dr)
return arbint[currentaint][node];
int mij = (st + dr) >> 1;
int maxs = -1,maxd = -1;
if(a <= mij) maxs = query(node << 1, st, mij, a, b, currentaint);
if(b > mij) maxd = query(node << 1 | 1, mij + 1, dr, a, b, currentaint);
return max(maxs,maxd);
}
int solve(int x, int y){
int ans = -1;
int lantx = where[x], lanty = where[y];
if(lantx == lanty)
{
int a = min(poz[x],poz[y]), b = max(poz[x], poz[y]);
ans = max(ans, query(1, 0, hp[lantx].size() - 1, a, b, lantx));
}
else
{
if(level[hp[lantx][0]] < level[hp[lanty][0]])
{
swap(x, y);
swap(lantx, lanty);
}
ans = max(ans, query(1, 0, hp[lantx].size() - 1, 0, poz[x], lantx));
ans = max(ans, solve(father[hp[lantx][0]],y));
}
return ans;
}
int main() {
int n,m;
fin >> n >> m;
for(int i = 1;i <= n; ++i)
fin >> nodevalue[i];
for(int i = 1; i< n; ++i)
{
int x, y;
fin >> x >> y;
graph[x].push_back(y);
graph[y].push_back(x);
}
hpd(1,0);
for (int i = 1; i <= nrhp; ++i)
reverse(hp[i].begin(), hp[i].end());
for (int i = 1; i<=n; ++i)
poz[i] = (int)hp[where[i]].size() - 1 - poz[i];
for (int i = 1; i<= nrhp; ++i){
arbint[i].resize(hp[i].size() << 2);
arint(1, 0, (int)hp[i].size() - 1, i);
}
for(int i = 1;i <= m; ++i)
{
int t, x, y;
fin >> t >> x >> y;
if(t == 1)
fout<< solve(x,y) << "\n";
else update(1, 0, hp[where[x]].size() - 1, poz[x], y ,where[x]);
}
return 0;
}