#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
struct SegmentTree
{
vector <int> nod;
SegmentTree (int _n)
{
nod.resize(4 * _n + 1, 0);
}
void update(int pos, int l, int r, int x, int val)
{
if(l == r)
{
nod[pos] = val;
return ;
}
int mid = (l + r) / 2;
if(x <= mid)
update(pos * 2, l, mid, x, val);
else
update(pos * 2 + 1, mid + 1, r, x, val);
nod[pos] = max(nod[pos * 2], nod[pos * 2 + 1]);
}
int query(int pos, int l, int r, int x, int y)
{
if(x <= l && r <= y)
return nod[pos];
int mid = (l + r) / 2;
int res = -1;
if(x <= mid) res = max(res, query(pos * 2, l, mid, x, y));
if(y > mid) res = max(res, query(pos * 2 + 1, mid + 1, r, x, y));
return res;
}
};
struct HLD
{
vector <vector <int> > adj;
vector <int> depth;
vector <int> position;
vector <int> subSize;
vector <int> parent;
vector <int> link;
HLD(int n)
{
adj.resize(n, vector <int> ());
depth.resize(n, 0);
position.resize(n, 0);
subSize.resize(n, 0);
parent.resize(n, 0);
link.resize(n, 0);
}
void addEdge(int x, int y)
{
adj[x].push_back(y);
adj[y].push_back(x);
}
void build()
{
dfs1(1, -1, 0);
dfs2(1, 1);
}
vector <pair <int, int> > getPath(int a, int b)
{
vector <pair <int, int> > aux;
while(link[a] != link[b])
{
if(depth[link[a]] < depth[link[b]])
swap(a, b);
aux.push_back({position[link[a]], position[a]});
a = parent[link[a]];
}
if(depth[a] < depth[b])
swap(a, b);
aux.push_back({position[b], position[a]});
return aux;
}
int dfs1(int nod, int prev, int low)
{
depth[nod] = low;
parent[nod] = prev;
subSize[nod] = 1;
if(prev != -1)
adj[nod].erase(find(adj[nod].begin(), adj[nod].end(), prev));
for(auto i : adj[nod])
subSize[nod] += dfs1(i, nod, low + 1);
return subSize[nod];
}
int timer = 0;
void dfs2(int nod, int to)
{
link[nod] = to;
position[nod] = timer++;
if(adj[nod].size() == 0)
return ;
pair <int, int> best = {-1, -1};
for(auto i : adj[nod])
best = max(best, {subSize[i], i});
dfs2(best.second, to);
for(auto i : adj[nod])
if(i != best.second)
dfs2(i, i);
}
};
main()
{
int n, m;
fin >> n >> m;
SegmentTree arb(n + 1);
HLD graf(n + 1);
vector <int> val(n);
for(auto &i : val)
fin >> i;
for(int i = 1; i < n; i++)
{
int x, y;
fin >> x >> y;
graf.addEdge(x, y);
}
graf.build();
for(int i = 1; i <= n; i++)
arb.update(1, 1, n, graf.position[i], val[i - 1]);
while(m--)
{
int t, x, y;
fin >> t >> x >> y;
if(t == 0)
{
arb.update(1, 1, n, graf.position[x], y);
}
else
{
int res = 0;
for(auto i : graf.getPath(x, y))
{
res = max(res, arb.query(1, 1, n, i.first, i.second));
}
fout << res << '\n';
}
}
}