#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int values[100005];
vector <int> v[100005];
int N, M;
struct Aint
{
int V[400005];
void update(int node, int l, int r, int poz, int val)
{
if(l == r)
{
V[node] = val;
return;
}
int mij = (l + r) / 2;
if(poz <= mij)
update(2 * node, l, mij, poz, val);
else
update(2 * node + 1, mij + 1, r, poz, val);
V[node] = max(V[2 * node], V[2 * node + 1]);
}
int query(int node, int l, int r, int ql, int qr)
{
if(l >= ql && r <= qr)
return V[node];
if(l > qr || r < ql)
return 0;
int mij = (l + r) / 2;
if(mij >= r)
return query(2 * node, l, mij, ql, qr);
else
if(mij < l)
return query(2 * node + 1, mij + 1, r, ql, qr);
else
return max(query(2 * node, l, mij, ql, qr), query(2 * node + 1, mij + 1, r, ql, qr));
}
void build(int node, int l, int r)
{
if(l == r)
{
V[node] = values[l];
return;
}
int mij = (l + r) / 2;
build(2 * node, l , mij);
build(2 * node + 1, mij + 1, r);
V[node] = max(V[2 * node], V[2 * node + 1]);
}
}aint;
int sz[100005], lvl[100005], dads[100005];
void dfs(int node, int dad)
{
dads[node] = dad;
lvl[node] = lvl[dad] + 1;
sz[node]++;
for(int i = 0; i < v[node].size(); i++)
if(v[node][i] != dad)
{
dfs(v[node][i], node);
sz[node] += sz[v[node][i]];
}
}
int label[100005], head[100005], k;
void dfsGreu(int node)
{
int fiu = v[node][0];
label[node] = ++k;
if(fiu == dads[node] && v[node].size() == 1)
return;
else
if(fiu == dads[node])
fiu = v[node][1];
for(int i = 0; i < v[node].size(); i++)
if(v[node][i] != dads[node])
if(sz[v[node][i]] > sz[fiu])
fiu = v[node][i];
head[fiu] = head[node];
dfsGreu(fiu);
for(int i = 0; i < v[node].size(); i++)
if(v[node][i] != dads[node] && v[node][i] != fiu)
dfsGreu(v[node][i]);
}
int Query(int x, int y)
{
if(head[x] == head[y])
{
x = label[x];
y = label[y];
if(x > y)
swap(x, y);
return aint.query(1, 1, N, x, y);
}
if(lvl[head[x]] > lvl[head[y]])
{
int ans = aint.query(1, 1, N, label[head[x]], label[x]);
return max(ans, Query(dads[head[x]], y));
}
else
{
int ans = aint.query(1, 1, N, label[head[y]], label[y]);
return max(ans, Query(x, dads[head[y]]));
}
}
int main()
{
fin >> N >> M;
for(int i = 1; i <= N; i++)
fin >> values[i];
for(int i = 1; i <= N - 1; i++)
{
int x, y;
fin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
aint.build(1, 1, N);
dfs(1, 0);
for(int i = 1; i <= N; i++)
head[i] = i;
dfsGreu(1);
for(int i = 1; i <= M; i++)
{
int t, x, y;
fin >> t >> x >> y;
if(t == 0)
aint.update(1, 1, N, x, y);
else
fout << Query(x, y) << '\n';
}
return 0;
}