#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int nmax = 100000;
int n, m, val[nmax + 5];
int nivel[nmax + 5], dim[nmax + 5], tata[nmax + 5], head[nmax + 5];
int pozHeavy[nmax + 5], cnt;
vector<int> g[nmax + 5];
struct AINT
{
int aint[4 * nmax + 5];
void build(int nod, int st, int dr)
{
if(st == dr)
{
aint[nod] = val[pozHeavy[st]];
return ;
}
int mid = (st + dr) >> 1;
build(2 * nod, st, mid);
build(2 * nod + 1, mid + 1, dr);
aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
void update(int nod, int st, int dr, int poz, int val)
{
if(st == dr)
{
aint[nod] = val;
return ;
}
int mid = (st + dr) >> 1;
if(poz <= mid)
{
update(2 * nod, st, mid, poz, val);
}
else
{
update(2 * nod, mid + 1, dr, poz, val);
}
aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
int query(int nod, int st, int dr, int l, int r)
{
if(st > r || dr < l || st > dr)
{
return 0;
}
if(st >= l && dr <= r)
{
return aint[nod];
}
int mid = (st + dr) >> 1;
return max(query(2 * nod, st, mid, l, r),
query(2 * nod + 1, mid + 1, dr, l, r));
}
};
AINT aint;
void dfs(int fiu, int nod)
{
nivel[fiu] = 1 + nivel[nod];
dim[fiu] = 1;
tata[fiu] = nod;
for(int i = 0; i != g[fiu].size(); i ++)
{
int it = g[fiu][i];
if(it == nod)
{
continue;
}
dfs(it, fiu);
dim[fiu] += dim[it];
}
}
void dfsHeavy(int fiu, int tata)
{
pozHeavy[fiu] = ++cnt;
int maxDist = 0, heavySon;
for(int i = 0; i != g[fiu].size(); i ++)
{
int it = g[fiu][i];
if(it == tata)
{
continue;
}
if(dim[it] > maxDist)
{
maxDist = dim[it];
heavySon = it;
}
}
if(maxDist == 0)
{
return ;
}
head[heavySon] = head[fiu];
dfsHeavy(heavySon, fiu);
for(int i = 0; i != g[fiu].size(); i ++)
{
int it = g[fiu][i];
if(it == tata || it == heavySon)
{
continue;
}
dfsHeavy(it, fiu);
}
}
int queryHeavy(int x, int y)
{
int sol = 0;
if(head[x] == head[y])
{
if(nivel[x] > nivel[y])
{
swap(x, y);
}
sol = aint.query(1, 1, n, pozHeavy[x], pozHeavy[y]);
}
else
{
if(nivel[head[x]] < nivel[head[y]])
{
swap(x, y);
}
sol = aint.query(1, 1, n, pozHeavy[head[x]], pozHeavy[x]);
x = tata[head[x]];
sol = max(sol, queryHeavy(x, y));
}
return sol;
}
int main()
{
fin >> n >> m;
for(int i = 1; i <= n; i ++)
{
fin >> val[i];
}
for(int i = 1; i < n; i ++)
{
int u, v;
fin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i = 1; i <= n; i ++)
{
head[i] = i;
}
dfs(1, 0);
dfsHeavy(1, 0);
aint.build(1, 1, n);
while(m--)
{
int type;
fin >> type;
if(type == 0)
{
int nod, valnew;
fin >> nod >> valnew;
aint.update(1, 1, n, pozHeavy[nod], valnew);
}
else
{
int x, y;
fin >> x >> y;
fout << queryHeavy(x, y) << '\n';
}
}
}