#include <fstream>
#include <vector>
#include <cmath>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int NMax = 1e5, BufferSize = 1e5;
char B[BufferSize + 5];
int N, M, K, Val[NMax + 5], W[NMax + 5], F[NMax + 5], P[NMax + 5], L[NMax + 5], Lev[NMax + 5], A[20][NMax + 5], TT[NMax + 5], AIT[4 * NMax + 5], Nr, pos;
vector <int> G[NMax + 5];
void DFS(int Nod, int Tata)
{
W[Nod] = 1, Lev[Nod] = Lev[Tata] + 1, A[0][Nod] = Tata;
for(auto Vecin : G[Nod])
if(Vecin != Tata)
DFS(Vecin, Nod), W[Nod] += W[Vecin];
}
int Parse() {
int Value = 0;
while(B[pos] < '0' || B[pos] > '9') {
pos++;
if(pos == BufferSize) {
fread(B, BufferSize, 1, stdin);
pos = 0;
}
}
while(B[pos] >= '0' && B[pos] <= '9') {
Value = Value * 10 + (B[pos] - '0');
pos++;
if(pos == BufferSize) {
fread(B, BufferSize, 1, stdin);
pos = 0;
}
}
return Value;
}
void MakePath(int Nod, int Tata, int c)
{
L[Nod] = c, P[Nod] = ++Nr;
if(F[c] == 0) F[c] = Nr;
int maxi = -1, x = 0;
for(auto Vecin : G[Nod])
{
if(Vecin != Tata && W[Vecin] > maxi)
maxi = W[Vecin], x = Vecin;
}
if(x) MakePath(x, Nod, c);
for(auto Vecin : G[Nod])
if(Vecin != Tata && Vecin != x)
{
TT[++K] = Nod;
MakePath(Vecin, Nod, K);
}
}
int Stramos(int Nod, int P)
{
int k = 0;
while(P)
{
if(P & 1) Nod = A[k][Nod];
P >>= 1, k++;
}
return Nod;
}
int LCA(int x, int y)
{
if(Lev[x] < Lev[y]) swap(x, y);
x = Stramos(x, Lev[x] - Lev[y]);
if(x == y) return x;
for(int i = log2(Lev[x]); i >= 0; i--)
{
if(A[i][x] != A[i][y])
x = A[i][x], y = A[i][y];
}
return A[0][x];
}
void Update(int i, int st, int dr, int p, int val)
{
if(p < st || dr < p) return;
if(st == dr)
{
AIT[i] = val;
return;
}
int m = (st + dr) / 2;
Update(2 * i, st, m, p, val);
Update(2 * i + 1, m + 1, dr, p, val);
AIT[i] = max(AIT[2 * i], AIT[2 * i + 1]);
}
int Querry(int i, int st, int dr, int a, int b)
{
if(b < st || dr < a) return 0;
if(a <= st && dr <= b)
return AIT[i];
int m = (st + dr) >> 1;
return max(Querry(2 * i, st, m, a, b), Querry(2 * i + 1, m + 1, dr, a, b));
}
int Solve(int x, int y)
{
int Sol = 0;
while(L[x] != L[y])
{
Sol = max(Sol, Querry(1, 1, N, F[L[x]], P[x]));
x = TT[L[x]];
}
return max(Sol, Querry(1, 1, N, P[y], P[x]));
}
void Precalc()
{
for(int i = 1; (1 << i) <= N; i++)
for(int j = 1; j <= N; j++)
A[i][j] = A[i - 1][A[i - 1][j]];
for(int i = 1; i <= N; i++)
Update(1, 1, N, P[i], Val[i]);
}
int main()
{
freopen("heavypath.in", "r", stdin);
fread(B, BufferSize, 1, stdin);
N = Parse(), M = Parse();
for(int i = 1; i <= N; i++)
Val[i] = Parse();
for(int i = 1, a, b; i < N; i++)
{
a = Parse(), b = Parse();
G[a].push_back(b);
G[b].push_back(a);
}
DFS(1, 0); MakePath(1, 0, ++K); Precalc();
while(M--)
{
int p = Parse(), x = Parse(), y = Parse();
if(p == 0)
Update(1, 1, N, P[x], y);
else
{
int c = LCA(x, y);
fout << max(Solve(x, c), Solve(y, c)) << '\n';
}
}
fin.close();
fout.close();
return 0;
}