#include <bits/stdc++.h>
#define NMAX (int)(1e5+4)
#define pb push_back
#define ft first
#define sd second
using namespace std;
FILE* fin=fopen("heavypath.in", "r");
FILE* fout=fopen("heavypath.out", "w");
typedef pair <int, int> pairINT;
typedef long long ll;
struct nod{
int pos, chain, depth;
};
nod nd[NMAX];
int n,q,l,id,w[NMAX],v[NMAX],sub[NMAX],up[NMAX],segm[4*NMAX],tata[NMAX];
vector <int> g[NMAX];
void read();
void dfs(int);
void buildChain(int);
void build(int,int,int);
void update(int,int,int,int,int);
int query(int,int,int,int,int);
int queryHeavy(int,int);
int main(){
read();
dfs(1);
buildChain(1); up[1]=1;
build(1,1,n);
int task,x,y;
while(q--){
fscanf(fin, "%d %d %d", &task, &x, &y);
if(task){
fprintf(fout, "%d\n", queryHeavy(x, y));
}else{
update(1,1,n,y,nd[x].pos);
}
}
return 0;
}
int queryHeavy(int x,int y){
int sol=0;
while(nd[x].chain != nd[y].chain){
if(nd[up[nd[x].chain]].depth > nd[up[nd[y].chain]].depth) swap(x, y);
sol=max(sol, query(1,1,n,nd[up[nd[y].chain]].pos, nd[y].pos));
y=tata[up[nd[y].chain]];
}
if(nd[x].depth > nd[y].depth) swap(x, y);
return max(sol, query(1,1,n,nd[x].pos,nd[y].pos));
}
void dfs(int node){//build chains
sub[node]=1;
nd[node].depth=nd[tata[node]].depth+1;
for(auto it:g[node])
if(it != tata[node]){
tata[it]=node;
dfs(it);
sub[node]+=sub[it];
}
}
void buildChain(int node){
int maxi=0;
nd[node].chain=id;
nd[node].pos=l;
v[l++]=node;
for(int i=0,it;i<g[node].size();++i){
it=g[node][i];
if(it != tata[node] && sub[maxi] < sub[it])
maxi=it;
}
if(maxi) buildChain(maxi);
for(auto it:g[node])
if(it != tata[node] && it != maxi){
++id;
up[id]=it;
buildChain(it);
}
}
int query(int node,int l,int r,int st,int dr){
if(st<=l && r<=dr){
return segm[node];
}
int mid=(l+r)>>1,sol=0;
if(st<=mid)
sol=max(sol, query(node<<1, l, mid, st, dr));
if(mid<dr)
sol=max(sol, query(node<<1 | 1, mid+1, r, st, dr));
return sol;
}
void update(int node,int l,int r,int val,int pos){
if(l == r){
segm[node]=val;
return;
}
int mid=(l+r)>>1;
if(pos<=mid)
update(node<<1, l, mid, val, pos);
else
update(node<<1|1, mid+1, r, val, pos);
segm[node]=max(segm[node<<1], segm[node<<1 | 1]);
}
void build(int node,int l,int r){
if(l == r){
segm[node]=w[v[l]];
return;
}
int mid=(l+r)>>1;
build(node<<1,l,mid);
build(node<<1 | 1,mid+1,r);
segm[node]=max(segm[node<<1], segm[node<<1 | 1]);
}
void read(){
fscanf(fin, "%d %d", &n, &q);
for(int i=1;i<=n;++i) fscanf(fin, "%d", &w[i]);
for(int i=1,x,y;i<n;++i){
fscanf(fin, "%d %d", &x, &y);
g[x].pb(y);
g[y].pb(x);
}
l=id=1;
}