#include <fstream>
#include <vector>
using namespace std;
ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");
int n, m;
int tree[400005];
vector <int> adj[100005];
int temp[100005];
int poz[100005];
int depth[100005];
int heavy[100005];
int dad[100005];
int head[100005];
int vec[100005];
int tim = 1;
void make(int nod, int st, int dr)
{
if (st == dr)
{
tree[nod] = vec[st];
return;
}
else
{
int mij = (st + dr) >> 1;
make(nod << 1, st, mij);
make(nod << 1 | 1, mij + 1, dr);
tree[nod] = max(tree[nod << 1], tree[nod << 1 | 1]);
}
}
void update(int nod, int st, int dr, int poz, int val)
{
if (st == dr)
{
tree[nod] = val;
} else
{
int mij = (st + dr) >> 1;
if (poz <= mij) update(nod << 1, st, mij, poz, val);
else update(nod << 1 | 1, mij + 1, dr, poz, val);
tree[nod] = max(tree[nod << 1], tree[nod << 1 | 1]);
}
}
int ans = -1;
void calc(int nod, int st, int dr, int a, int b)
{
if (a <= st && dr <= b)
{
ans = max(ans, tree[nod]);
} else
{
int mij = (st + dr) >> 1;
if (a <= mij) calc(nod << 1, st, mij, a, b);
if (b > mij) calc(nod << 1 | 1, mij + 1, dr, a, b);
}
}
int dfs(int nod, int parinte)
{
int sizeNod = 1;
int maxx = 0;
int sizeX = 0;
heavy[nod] = -1;
dad[nod] = parinte;
for (const auto& x : adj[nod])
{
if (x != parinte)
{
depth[x] = depth[nod] + 1;
sizeX = dfs(x, nod);
sizeNod += sizeX;
if (sizeX > maxx)
{
maxx = sizeX;
heavy[nod] = x;
}
}
}
return sizeNod;
}
void decompose(int nod, int parinte, int cap)
{
head[nod] = cap;
poz[nod] = tim++;
if (heavy[nod] != -1)
{
decompose(heavy[nod], nod, cap);
}
for (const auto& x : adj[nod])
{
if (x != parinte && heavy[nod] != x)
{
decompose(x, nod, x);
}
}
}
int query(int u, int v)
{
int rez = -1;
while (head[u] != head[v])
{
if (depth[head[u]] > depth[head[v]])
{
swap(u, v);
}
ans = -1;
calc(1, 1, n, poz[head[v]], poz[v]);
rez = max(rez, ans);
v = dad[head[v]];
}
if (depth[u] > depth[v]) swap(u, v);
ans = -1;
calc(1, 1, n, poz[u], poz[v]);
rez = max(rez, ans);
return rez;
}
int u, v;
int main()
{
cin.tie(NULL);
ios_base::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> temp[i];
}
for (int i = 1; i < n; i++)
{
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
depth[1] = 0;
dfs(1, 0);
decompose(1, 0, 1);
for (int i = 1; i <= n; i++)
{
vec[poz[i]] = temp[i];
}
make(1, 1, n);
for (int i = 0; i < m; i++)
{
int tip, x, y;
cin >> tip >> x >> y;
if (tip == 0)
{
update(1, 1, n, poz[x], y);
}
else
{
cout << query(x, y) << "\n";
}
}
return 0;
}