#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int dim=100009;
vector<int>g[dim];///folosit doar la inceput
vector<int>v[dim];///pentru arborele final
////////////////////////////////////////////////////////////////////////pentru lca
int len,nivel[dim];
int euler[2*dim],aparitie[2*dim];
int logaritm[2*dim],rmq[2*dim][20];
void DFS(int x,int tata){
euler[++len]=x;
nivel[x]=nivel[tata]+1;
aparitie[x]=len;
for(int y:v[x]){
DFS(y,x);
euler[++len]=x;
}
}
void generare(){
for(int i=2;i<=len;i++){
logaritm[i]=logaritm[i/2]+1;
}
for(int i=1;i<=len;i++){
rmq[i][0]=i;
}
for(int j=1;(1<<j)<=len;j++){
for(int i=1;i+(1<<j)-1<=len;i++){
int l=rmq[i][j-1];
int r=rmq[i+(1<<(j-1))][j-1];
rmq[i][j]=(nivel[euler[l]]<nivel[euler[r]]) ? l : r;
}
}
}
int lca(int a,int b){
a=aparitie[a];
b=aparitie[b];
if(a>b){
swap(a,b);
}
int log=logaritm[b-a+1];
int l=rmq[a][log];
int r=rmq[b-(1<<log)+1][log];
return (nivel[euler[l]]<nivel[euler[r]]) ? euler[l] : euler[r];
}
void find_lca(){
DFS(1,0);
generare();
}
////////////////////////////////////////////////////////////////////////
bool vizitat[dim];
int sz[dim],parent[dim];
void dfs_size(int x,int tata){
vizitat[x]=1;
sz[x]=1;
for(int y:g[x]){
if(!vizitat[y]){
dfs_size(y,x);
parent[y]=x;
v[x].push_back(y);
sz[x]+=sz[y];
}
}
}
struct SegmentTree{
vector<int>aint;
void init(int lungime){
for(int i=0;i<=4*lungime;i++){
aint.push_back(0);
}
}
void update(int nod,int tl,int tr,int poz,int val){
if(tl==tr){
aint[nod]=val;
return;
}
int tm=(tl+tr)/2;
if(poz<=tm){
update(2*nod,tl,tm,poz,val);
}
else{
update(2*nod+1,tm+1,tr,poz,val);
}
aint[nod]=max(aint[2*nod],aint[2*nod+1]);
}
int query(int nod,int tl,int tr,int l,int r){
if(l==tl && r==tr){
return aint[nod];
}
int tm=(tl+tr)/2;
if(r<=tm){
return query(2*nod,tl,tm,l,r);
}
if(l>tm){
return query(2*nod+1,tm+1,tr,l,r);
}
return max(query(2*nod,tl,tm,l,tm),query(2*nod+1,tm+1,tr,tm+1,r));
}
}aint[dim];
int nr_comp;///nr total de componenete
int comp[dim];///componenta int care se afla nodul x
int len_comp[dim];///lungimea componenetei i
int poz_comp[dim];///pozitia in componenta a lui x
int cap_comp[dim];///capul componenei i
int val[dim];
void HPD(int x,bool schimba,int comp_tata){///generare lanturi HPD
int comp_locala;
if(schimba){
nr_comp++;
comp_locala=nr_comp;
cap_comp[comp_locala]=x;
}
else{
comp_locala=comp_tata;
}
comp[x]=comp_locala;
len_comp[comp_locala]++;
poz_comp[x]=len_comp[comp_locala];
for(int y:v[x]){
if(sz[y]>sz[x]/2||v[x].size()==1){
HPD(y,0,comp_locala);
}
else{
HPD(y,1,comp_locala);
}
}
}
bool initializat[dim];
signed main(){
int n,q;
fin>>n>>q;
for(int i=1;i<=n;i++){
fin>>val[i];
}
for(int i=2;i<=n;i++){
int x,y;
fin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs_size(1,0);
find_lca();
HPD(1,1,0);
for(int i=1;i<=n;i++){
if(!initializat[comp[i]]){
aint[comp[i]].init(len_comp[comp[i]]);
initializat[comp[i]]=true;
}
aint[comp[i]].update(1,1,len_comp[comp[i]],poz_comp[i],val[i]);
}
while(q--){
int op;
fin>>op;
if(op==0){
int poz,val;
fin>>poz>>val;
aint[comp[poz]].update(1,1,len_comp[comp[poz]],poz_comp[poz],val);
}
else{
int l,r;
fin>>l>>r;
int c=lca(l,r);
int ans=0;
while(comp[l]!=comp[c]){
ans=max(ans,aint[comp[l]].query(1,1,len_comp[comp[l]],1,poz_comp[l]));
l=parent[cap_comp[comp[l]]];
}
ans=max(ans,aint[comp[l]].query(1,1,len_comp[comp[l]],poz_comp[c],poz_comp[l]));
while(comp[r]!=comp[c]){
ans=max(ans,aint[comp[r]].query(1,1,len_comp[comp[r]],1,poz_comp[r]));
r=parent[cap_comp[comp[r]]];
}
ans=max(ans,aint[comp[r]].query(1,1,len_comp[comp[r]],poz_comp[c],poz_comp[r]));
fout<<ans<<endl;
}
}
}