#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#define pii pair <int, int>
string filename = "heavypath";
#ifdef LOCAL
ifstream fin("input.in");
ofstream fout("output.out");
#else
ifstream fin(filename + ".in");
ofstream fout(filename + ".out");
#endif
const int NMAX = 1e5;
int n;
int v[NMAX + 1];
vector <int> adj[NMAX + 1];
int par[NMAX + 1];
int sz[NMAX + 1];
int lvl[NMAX + 1];
int heavy[NMAX + 1];
void explore(int node, int parent){
sz[node] = 1;
par[node] = parent;
lvl[node] = lvl[parent] + 1;
for(int child : adj[node]){
if(child != parent){
explore(child, node);
sz[node] += sz[child];
if(sz[child] > sz[heavy[node]]){
heavy[node] = child;
}
}
}
}
int lin[NMAX + 1];
pii pos[NMAX + 1];
int id[NMAX + 1];
int head[NMAX + 1];
int Id = 0;
int dfsTime = 0;
void heavyfirst(int node, int parent){
++dfsTime;
lin[dfsTime] = node;
pos[node].first = dfsTime;
if(heavy[parent] == node){
id[node] = id[parent];
}else{
++Id;
id[node] = Id;
head[Id] = node;
}
if(heavy[node] != 0){
heavyfirst(heavy[node], node);
}
for(int child : adj[node]){
if(child != parent && child != heavy[node]){
heavyfirst(child, node);
}
}
pos[node].second = dfsTime;
}
namespace AINT{
int aint[4 * NMAX + 1];
void build(int node, int l, int r){
if(l == r){
aint[node] = v[lin[l]];
return;
}
int mid = (l + r) / 2;
build(2 * node, l, mid);
build(2 * node + 1, mid + 1, r);
aint[node] = max(aint[2 * node], aint[2 * node + 1]);
}
void update(int node, int l, int r, int pos, int val){
if(l == r){
aint[node] = val;
return;
}
int mid = (l + r) / 2;
if(pos <= mid){
update(2 * node, l, mid, pos, val);
}else{
update(2 * node + 1, mid + 1, r, pos, val);
}
aint[node] = max(aint[2 * node], aint[2 * node + 1]);
}
int query(int node, int l, int r, int ql, int qr){
if(ql <= l && r <= qr){
return aint[node];
}
int mid = (l + r) / 2, ans = 0;
if(ql <= mid){
ans = max(ans, query(2 * node, l, mid, ql, qr));
}
if(mid + 1 <= qr){
ans = max(ans, query(2 * node + 1, mid + 1, r, ql, qr));
}
return ans;
}
}
int query(int x, int y){
int ans = 0;
while(id[x] != id[y]){
if(lvl[head[id[x]]] > lvl[head[id[y]]]){
ans = max(ans, AINT::query(1, 1, n, pos[head[id[x]]].first, pos[x].first));
x = par[head[id[x]]];
}else{
ans = max(ans, AINT::query(1, 1, n, pos[head[id[y]]].first, pos[y].first));
y = par[head[id[y]]];
}
}
int a = pos[x].first;
int b = pos[y].first;
ans = max(ans, AINT::query(1, 1, n, min(a, b), max(a, b)));
return ans;
}
signed main(){
int q;
fin >> n >> q;
for(int i = 1; i <= n; i++){
fin >> v[i];
}
for(int i = 1; i <= n - 1; i++){
int a, b;
fin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
explore(1, 0);
heavyfirst(1, 0);
AINT::build(1, 1, n);
while(q--){
int type;
fin >> type;
if(type == 0){
int x, y;
fin >> x >> y;
AINT::update(1, 1, n, pos[x].first, y);
}else{
int x, y;
fin >> x >> y;
fout << query(x, y) << '\n';
}
}
return 0;
}