#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define pf push_front
#define MOD 1000000007
#define MAX 100005
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int val[MAX], arb[4*MAX];
vector < int > v[MAX], ind;
int n, nvl[MAX], t[MAX], heavy[MAX], radacina_heavy_path[MAX], coresp[MAX], r;
void dfs(int nod, int prec);
int set_heavy(int nod);
void set_arbint(int nod);
void rezolva(int u, int v);
void construieste(int nod, int st, int dr)
{
int mij;
if(st == dr) arb[nod] = val[ind[st]];
else
{
mij = (st + dr) / 2;
construieste(2 * nod, st, mij);
construieste(2 * nod + 1, mij + 1, dr);
arb[nod] = max(arb[2*nod], arb[2*nod+1]);
}
}
void update(int nod, int st, int dr, int poz, int val)
{
int mij;
if(st == dr) arb[nod] = val;
else
{
mij = (st + dr) / 2;
if(poz <= mij) update(2 * nod, st, mij, poz, val);
else update(2 * nod + 1, mij + 1, dr, poz, val);
arb[nod] = max(arb[2*nod], arb[2*nod+1]);
}
}
int query(int nod, int st, int dr, int x, int y)
{
int mij;
if(x <= st && y >= dr) return arb[nod];
else
{
mij = (st + dr) / 2;
if(x > mij) return query(2 * nod + 1, mij + 1, dr, x, y);
else if(y <= mij) return query(2 * nod, st, mij, x, y);
else return max(query(2 * nod + 1, mij + 1, dr, x, y), query(2 * nod, st, mij, x, y));
}
}
int main()
{
int q, i, x, y, t;
fin >> n >> q;
for(i = 1; i <= n; i++) fin >> val[i];
for(i = 1; i < n; i++) fin >> x >> y, v[x].pb(y), v[y].pb(x);
dfs(1, 0);
for(i = 1; i <= n; i++) radacina_heavy_path[i] = i;
set_heavy(1), ind.pb(0), set_arbint(1);
construieste(1, 1, n);
while(q--)
{
fin >> t >> x >> y;
if(t == 0) update(1, 1, n, coresp[x], y);
else
{
r = 0;
rezolva(x, y);
fout << r << '\n';
}
}
return 0;
}
void dfs(int nod, int prec)
{
nvl[nod] = nvl[prec] + 1, t[nod] = prec;
for(auto it:v[nod]) if(nvl[it] == 0) dfs(it, nod);
}
int set_heavy(int nod)
{
int s = 1, x, maxx = 0;
for(auto it:v[nod])
if(it != t[nod])
{
x = set_heavy(it);
s += x;
if(x > maxx) maxx = x, heavy[nod] = it;
}
if(heavy[nod] != 0) radacina_heavy_path[heavy[nod]] = radacina_heavy_path[nod];
return s;
}
void set_arbint(int nod)
{
ind.pb(nod), coresp[nod] = ind.size() - 1;
if(heavy[nod] != 0) set_arbint(heavy[nod]);
for(auto it:v[nod]) if(it != t[nod] && it != heavy[nod]) set_arbint(it);
}
void rezolva(int u, int v)
{
int x = radacina_heavy_path[u], y = radacina_heavy_path[v], z;
if(x == y)
{
z = query(1, 1, n, min(coresp[u], coresp[v]), max(coresp[u], coresp[v]));
r = max(r, z);
}
else if(nvl[x] >= nvl[y])
{
z = query(1, 1, n, min(coresp[u], coresp[x]), max(coresp[u], coresp[x]));
r = max(r, z);
rezolva(t[x], v);
}
else
{
z = query(1, 1, n, min(coresp[v], coresp[y]), max(coresp[v], coresp[y]));
r = max(r, z);
rezolva(u, t[y]);
}
}