#include <bits/stdc++.h>
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
const int N = 100005, LOG = 18;
int n, q;
vector <int> L[N];
bool viz[N];
int value[N], path[N], pos[N], pathParent[LOG], level[N];
int dp[N], cntPaths, len[LOG];
int aint[LOG][4 * N];
void updateAint(int p, int node, int st, int dr, int targetPos, int val)
{
if (st == dr)
{
aint[p][node] = val;
return;
}
int mij = (st + dr) / 2;
if (targetPos <= mij)
updateAint(p, 2 * node, st, mij, targetPos, val);
else
updateAint(p, 2 * node + 1, mij + 1, dr, targetPos, val);
aint[p][node] = max(aint[p][2 * node], aint[p][2 * node + 1]);
}
int queryAint(int p, int node, int st, int dr, int lft, int rgt)
{
if (st >= lft && dr <= rgt)
return aint[p][node];
else
{
int mij = (st + dr) / 2;
int q1 = 0, q2 = 0;
if (lft <= mij)
q1 = queryAint(p, 2 * node, st, mij, lft, rgt);
if (rgt >= mij + 1)
q2 = queryAint(p, 2 * node + 1, mij + 1, dr, lft, rgt);
return max(q1, q2);
}
}
int Query(int x, int y)
{
int ans = 0;
bool ok = 0;
while (!ok)
{
if (level[pathParent[x]] > level[pathParent[y]])
swap(x, y);
if (path[x] == path[y])
{
int lft = min(pos[x], pos[y]);
int rgt = max(pos[x], pos[y]);
ans = max(ans, queryAint(path[x], 1, 1, len[path[x]], lft, rgt));
ok = 1;
}
else
{
ans = max(ans, queryAint(path[x], 1, 1, len[path[x]], 1, pos[x]));
x = pathParent[path[x]];
}
}
return ans;
}
void DFS(int node, int task)
{
viz[node] = 1;
if (task == 1)
{
if (L[node].size() == 1 && node != 1)
path[node] = ++cntPaths;
for (int nextNode : L[node])
if (!viz[nextNode])
{
int maxim = 0;
level[nextNode] = level[node] + 1;
DFS(nextNode, task);
dp[node] += dp[nextNode];
if (maxim < path[nextNode])
{
maxim = path[nextNode];
path[node] = path[nextNode];
}
}
dp[node]++;
for (int nextNode : L[node])
{
if (path[node] != path[nextNode])
pathParent[path[nextNode]] = node;
}
}
else
{
pos[node] = ++len[path[node]];
for (int nextNode : L[node])
if (!viz[nextNode])
DFS(nextNode, task);
updateAint(path[node], 1, 1, len[path[node]], pos[node], value[node]);
}
}
int main()
{
fin >> n >> q;
for (int i = 1; i <= n; i++)
fin >> value[i];
for (int i = 1; i < n; i++)
{
int a, b;
fin >> a >> b;
L[a].push_back(b);
L[b].push_back(a);
}
level[1] = 1;
DFS(1, 1);
for (int i = 1; i <= n; i++)
viz[i] = 0;
DFS(1, 2);
while(q--)
{
int op, x, y;
fin >> op >> x >> y;
if (op == 0)
updateAint(path[x], 1, 1, len[path[x]], pos[x], y);
else
fout << Query(x, y) << "\n";
}
return 0;
}