#include <bits/stdc++.h>
#define DIM 200001
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int father[DIM], sz[DIM], depth[DIM], chain_idx[DIM], chain_pos[DIM], chain_size[DIM], tin[DIM], tout[DIM], leaf[DIM], v[DIM];
int RMQ[int32_t(log2(DIM)) + 1][DIM];
vector <int> G[DIM];
struct nod{
int answer, ret;
};
vector < vector <nod> > wmt;
vector <int> pos[DIM];
int t, Q, n, task, x, y, total_chains, i, j, lca;
void dfs(int node, int dad){
father[node] = dad;
depth[node] = depth[father[node]] + 1;
sz[node] = 1;
tin[node] = ++t;
for(auto k : G[node])
if(k != dad){
dfs(k, node);
sz[node] += sz[k];
}
if(G[node].size() == 1 && node != 1)
leaf[node] = true;
tout[node] = ++t;
}
void build_chains(int node, int idx){
chain_idx[node] = idx;
chain_pos[node] = ++chain_size[chain_idx[node]];
pos[idx].push_back(node);
if(leaf[node])
return ; // am ajuns la capatul lantului
int ret = 0;
for(auto k : G[node])
if(k != father[node] && (!ret || sz[k] > sz[ret]))
ret = k;
// continui lantul asta cu ret
for(auto k : G[node])
if(k != father[node] && k != ret) // cel mai greu lant (Maciuca / Costinel)
build_chains(k, ++total_chains);
build_chains(ret, idx);
}
nod Combine(nod st, nod dr){
nod answer;
if(st.answer >= dr.answer)
answer = st;
else answer = dr;
return answer;
}
void Build_Tree(int state, int node, int st, int dr){
if(st == dr) {
wmt[state][node].answer = v[pos[state][st - 1]];
wmt[state][node].ret = st;
}
else {
int mij = (st + dr) >> 1;
Build_Tree(state, node << 1, st, mij);
Build_Tree(state, node << 1 | 1, mij + 1, dr);
wmt[state][node] = Combine(wmt[state][node << 1], wmt[state][node << 1 | 1]);
}
}
void Update(int state, int node, int st, int dr, int a, int b){
if(st == dr)
wmt[state][node].answer = b;
else {
int mij = (st + dr) >> 1;
if(a <= mij)
Update(state, node << 1, st, mij, a, b);
else Update(state, node << 1 | 1, mij + 1, dr, a, b);
wmt[state][node] = Combine(wmt[state][node << 1], wmt[state][node << 1 | 1]);
}
}
nod Query(int state, int node, int st, int dr, int a, int b){
if(dr < a || st > b)
return {0, 0};
if(st >= a && dr <= b)
return wmt[state][node];
else {
int mij = (st + dr) >> 1;
nod ok1 = Query(state, node << 1, st, mij, a, b);
nod ok2 = Query(state, node << 1 | 1, mij + 1, dr, a, b);
return Combine(ok1, ok2);
}
}
int get_ancestor(int n, int k){
for(int bit=20;bit>=0;bit--)
if((k >> bit) & 1)
n = RMQ[bit][n];
return n;
}
bool is_ancestor(int x, int y){
if(tin[x] <= tin[y] && tout[y] <= tout[x])
return true;
return false;
}
int LCA(int x, int y){
int st = 0, dr = depth[x] - 1;
int ret = x;
while(st <= dr){
int mij = (st + dr) >> 1;
if(is_ancestor(get_ancestor(x, mij), y)){
ret = mij;
dr = mij - 1;
}
else st = mij + 1;
}
return get_ancestor(x, ret);
}
int solve(int start, int finish){
int ret = 0;
while(chain_idx[start] != chain_idx[finish]){
ret = max(ret, Query(chain_idx[start], 1, 1, chain_size[chain_idx[start]], 1, chain_pos[start]).answer);
start = father[pos[chain_idx[start]][0]];
}
ret = max(ret, Query(chain_idx[start], 1, 1, chain_size[chain_idx[start]], chain_pos[finish], chain_pos[start]).answer);
return ret;
}
int main(){
fin >> n >> Q;
for(i=1;i<=n;i++)
fin >> v[i];
for(i=2;i<=n;i++){
fin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1, 0);
total_chains = 1;
build_chains(1, 1);
wmt.resize(total_chains + 5);
for(i=1;i<=total_chains;i++)
wmt[i].resize(4 * ( chain_size[i] + 5) );
for(i=1;i<=total_chains;i++)
Build_Tree(i, 1, 1, chain_size[i]);
return 0;
for(i=1;i<=n;i++)
RMQ[0][i] = father[i];
for(i=1;(1<<i)<=n;i++)
for(j=1;j<=n;j++)
RMQ[i][j] = RMQ[i - 1][RMQ[i - 1][j]];
while(Q--){
fin >> task >> x >> y;
if(task == 0)
Update(chain_idx[x], 1, 1, chain_size[chain_idx[x]], chain_pos[x], y);
else {
lca = LCA(x, y);
fout << max(solve(x, lca), solve(y, lca)) << "\n";
}
}
}