#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
const int MAX = 100005;
int n, m, t, x, y, z, nrchain;
int v[MAX], h[MAX], size[MAX], ind[MAX], poz[MAX], nodes[MAX], pLant[MAX], arb[MAX];
vector<int> l[MAX], chain[MAX];
bool viz[MAX];
void dfs(int x, int p){
int best = 0;
h[x] = h[p] + 1;
size[x] = 1;
for(int i = 0; i < l[x].size(); ++i)
if(l[x][i] != p){
dfs(l[x][i], x);
size[x] += size[l[x][i]];
if(size[best] < size[l[x][i]])
best = l[x][i];
}
for(int i = 0; i < l[x].size(); ++i)
if(l[x][i] != p && l[x][i] != best)
pLant[ind[l[x][i]]] = x;
if(best == 0)
ind[x] = ++nrchain;
else
ind[x] = ind[best];
chain[ind[x]].push_back(x);
}
void buildArb(){
for(int i = n; i > 0; --i)
arb[i] = max(arb[2 * i], arb[2 * i + 1]);
}
void update(int pos, int val){
arb[pos + n] = val;
pos += n;
for(; pos > 1; pos >>= 1)
arb[pos>>1] = max(arb[pos], arb[pos ^ 1]);
}
int query(int x, int y){
int res = 0;
x += n;
y += n;
while(x < y){
if(x & 1)
res = max(res, arb[x++]);
if(y & 1)
res = max(res, arb[--y]);
x >>= 1;
y >>= 1;
}
return res;
}
int hpd(int x, int y){
int res = 0;
while(ind[x] != ind[y]){
if(h[ind[x]] < h[ind[y]])
swap(x, y);
res = max(res, query(poz[x], poz[chain[ind[x]].back()] + 1));
x = pLant[ind[x]];
}
if(poz[x] > poz[y])
swap(x, y);
return max(res, query(poz[x], poz[y] + 1));
}
int main(){
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &v[i]);
for(int i = 0; i < n - 1; ++i){
scanf("%d%d", &x, &y);
l[x].push_back(y);
l[y].push_back(x);
}
dfs(1, 0);
int nr = 0;
for(int i = 1; i <= nrchain; ++i)
for(int j = 0; j < chain[i].size(); ++j){
poz[chain[i][j]] = ++nr;
nodes[nr] = chain[i][j];
arb[nr + n] = v[chain[i][j]];
}
buildArb();
for(int i = 0; i < m; i++){
scanf("%d%d%d", &t, &x, &y);
if(t == 0)
update(poz[x], y);
if(t == 1)
printf("%d\n", hpd(x, y));
}
return 0;
}