#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, m, k, maxi, ord_lant, a[100005], b[100005], subarbore[100005], lant[100005], poz[100005];
int first[100005], urmatorul_lant[100005], urmatorul_nod[100005];
int aint[525005];
bool viz[100005];
vector<int> G[100005];
void Subarbore(int x)
{
subarbore[x] = 1;
viz[x] = 1;
for(int e : G[x])
if(viz[e] == 0)
{
Subarbore(e);
subarbore[x] += subarbore[e];
}
}
void Lanturi(int x)
{
int i, j;
viz[x] = 1;
lant[x] = ord_lant;
b[++k] = a[x];poz[x] = k;
i = 0;j = -1;
while(i < G[x].size() && viz[G[x][i]] == 1)
i++;
if(i < G[x].size()) j = i, i++;
for( ;i < G[x].size();i++)
if(viz[G[x][i]] == 0 && subarbore[G[x][i]] > subarbore[G[x][j]])
j = i;
if(j > -1)
Lanturi(G[x][j]);
for(i = 0;i < G[x].size();i++)
if(viz[G[x][i]] == 0 && i != j)
{
ord_lant++;
urmatorul_nod[ord_lant] = poz[x];
urmatorul_lant[ord_lant] = lant[x];
first[ord_lant] = k + 1;
Lanturi(G[x][i]);
}
}
void Creare_Arbore(int nod, int st, int dr)
{
if(st == dr)
{
aint[nod] = b[st];
return ;
}
int mij = (st + dr) / 2;
Creare_Arbore(2 * nod, st, mij);
Creare_Arbore(2 * nod + 1, mij + 1, dr);
aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
void Update(int nod, int st, int dr, int p, int val)
{
if(st == dr)
{
aint[nod] = val;
return ;
}
int mij = (st + dr) / 2;
if(p <= mij)
Update(2 * nod, st, mij, p, val);
else Update(2 * nod + 1, mij + 1, dr, p, val);
aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
void Query(int nod, int st, int dr, int x, int y)
{
if(x <= st && dr <= y)
{
maxi = max(maxi, aint[nod]);
return ;
}
int mij = (st + dr) / 2;
if(x <= mij)
Query(2 * nod, st, mij, x, y);
if(mij + 1 <= y)
Query(2 * nod + 1, mij + 1, dr, x, y);
}
int Solve(int x, int y)
{
int pozitie_x = poz[x], pozitie_y = poz[y];
int lant_x = lant[x], lant_y = lant[y];
maxi = 0;
while(lant_x != lant_y)
{
if(pozitie_x > pozitie_y)
{
Query(1, 1, n, first[lant_x], pozitie_x);
pozitie_x = urmatorul_nod[lant_x];
lant_x = urmatorul_lant[lant_x];
}
else{
Query(1, 1, n, first[lant_y], pozitie_y);
pozitie_y = urmatorul_nod[lant_y];
lant_y = urmatorul_lant[lant_y];
}
}
Query(1, 1, n, min(pozitie_x, pozitie_y), max(pozitie_x, pozitie_y));
return maxi;
}
int main()
{
int i, j, op;
fin >> n >> m;
for(i = 1;i <= n;i++)
fin >> a[i];
for(int ind = 1;ind < n;ind++)
{
fin >> i >> j;
G[i].push_back(j);
G[j].push_back(i);
}
Subarbore(1);
for(i = 1;i <= n;i++)
viz[i] = 0;
ord_lant = 1;first[1] = 1;urmatorul_nod[1] = 1;urmatorul_lant[1] = 1;
Lanturi(1);
Creare_Arbore(1, 1, n);
while(m)
{
fin >> op >> i >> j;
if(op == 1)
fout << Solve(i, j) << "\n";
else Update(1, 1, n, poz[i], j);
m--;
}
fout.close();
return 0;
}