#include <bits/stdc++.h>
// #define in cin
// #define out cout
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
const int nmax = 1e5 + 5e0;
const int lgmax = 17;
int n, m;
int v[nmax];
vector<int> adj[nmax];
int parent[nmax];
int depth[nmax];
int aint[3 * nmax];
int aintIndex[nmax];
vector<int> paths;
int pIndex[nmax];
bool pathEnd[nmax];
int psize[nmax];
int pind;
void update(int poz, int val, int st = 1, int dr = n, int nod = 1)
{
if (st == dr)
{
aint[nod] = val;
}
else
{
int mid = (st + dr) / 2;
if (poz <= mid)
{
update(poz, val, st, mid, 2 * nod);
}
else
{
update(poz, val, mid + 1, dr, 2 * nod + 1);
}
aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
}
int query(int l, int r, int st = 1, int dr = n, int nod = 1)
{
if (l == st && r == dr)
{
return aint[nod];
}
else
{
int mid = (st + dr) / 2;
if (r <= mid)
return query(l, r, st, mid, 2 * nod);
else if (mid < l)
return query(l, r, mid + 1, dr, 2 * nod + 1);
else
{
return max(
query(l, mid, st, mid, 2 * nod),
query(mid + 1, r, mid + 1, dr, 2 * nod + 1));
}
}
}
int ind = 1;
void dfs(int nod = 1, int p = 0, int dep = 0)
{
parent[nod] = p;
psize[nod] = 1;
depth[nod] = dep;
vector<int> path;
int maxx = 0;
for (auto i : adj[nod])
{
if (i != p)
{
dfs(i, nod, dep + 1);
maxx = max(maxx, psize[i]);
}
}
bool found = 0;
for (auto i : adj[nod])
{
if (psize[i] == maxx && !found && i != p)
{
psize[nod] += maxx;
found = 1;
}
else if(i!=p)
{
//cerr << nod << ' ' << i << '\n';
pathEnd[i] = 1;
}
}
}
void readInput()
{
in >> n >> m;
for (int i = 1; i <= n; i++)
{
in >> v[i];
}
for (int i = 1; i < n; i++)
{
int a, b;
in >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
pathEnd[1] = 1;
}
int q(int x, int y)
{
int ans = 0;
while (1)
{
auto px = paths[pIndex[x]];
auto py = paths[pIndex[y]];
//cerr << x << ' ' << y << '\n';
//cerr << px << ' ' << py << '\n';
if (px == py)
{
if (depth[x] > depth[y])
{
swap(x, y);
}
ans = max(ans, query(aintIndex[y], aintIndex[x]));
break;
}
else
{
if (depth[px] < depth[py])
{
swap(x, y);
swap(px, py);
}
ans = max(ans, query(aintIndex[x], aintIndex[px]));
x = parent[px];
}
}
return ans;
}
void solve()
{
for (int i = 1; i <= n; i++)
{
update(aintIndex[i], v[i]);
}
for (int i = 0; i < m; i++)
{
int t, x, y;
in >> t >> x >> y;
if (t == 0)
{
v[x] = y;
update(aintIndex[x], y);
}
else
{
out << q(x, y) << '\n';
}
}
}
void calcPath(int node)
{
aintIndex[node] = ind++;
pIndex[node] = pind;
if (pathEnd[node])
{
paths.push_back(node);
}
else
{
calcPath(parent[node]);
}
}
void doPaths()
{
for (int i = 1; i <= n; i++)
{
if (adj[i].size() - (parent[i] != 0) == 0)
{
calcPath(i);
pind++;
}
}
}
int main()
{
readInput();
dfs();
doPaths();
// for (int i = 0; i < paths.size(); i++)
// cerr << paths[i] << ' ';
// cerr << '\n';
// for (int i = 1; i <= n; i++)
// cerr << pIndex[i] << ' ';
// cerr << '\n';
solve();
}