#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int NMAX = 100005;
int a[NMAX],nivel[NMAX],parent[NMAX],arb_dim[NMAX],decalare[NMAX],aint[4*NMAX];
int nr_lanturi,ind_lant[NMAX],parinte_lant[NMAX],pozitia_in_lant[NMAX];
vector <int> v[NMAX],lant[NMAX];
int operatie,x,y,n,m;
bool ver[NMAX];
void dfs(int node,int niv,int p){
ver[node]=true;
nivel[node]=niv;
parent[node]=p;
arb_dim[node]=1;
int max_node=0,max_dim=0;
for(int i=0;i<v[node].size();i++){
int vecin=v[node][i];
if(ver[vecin]==true) continue;
dfs(vecin,niv+1,node);
arb_dim[node]+=arb_dim[vecin];
if(arb_dim[vecin]>max_dim){
max_dim=arb_dim[vecin];
max_node=vecin;
}
}
if(max_dim==0){
lant[++nr_lanturi].push_back(node);
ind_lant[node]=nr_lanturi;
parinte_lant[nr_lanturi]=parent[node];
} else {
int ind=ind_lant[max_node];
lant[ind].push_back(node);
ind_lant[node]=ind;
parinte_lant[ind]=parent[node];
}
}
void update(int node,int st,int dr,int poz,int val,int decalare){
if(st>dr) return;
if(st==dr and st==poz){
aint[node+decalare]=val;
return;
}
int mij=(st+dr)/2;
if(poz<=mij) update(2*node,st,mij,poz,val,decalare);
else update(2*node+1,mij+1,dr,poz,val,decalare);
aint[node+decalare]=max(aint[2*node+decalare],aint[2*node+1+decalare]);
}
int query(int node,int st,int dr,int qst,int qdr,int decalare){
if(qst<=st and dr<=qdr){
return aint[node+decalare];
}
int mij=(st+dr)/2;
int x=0,y=0;
if(qst<=mij) x=query(2*node,st,mij,qst,qdr,decalare);
if(qdr>mij) y=query(2*node+1,mij+1,dr,qst,qdr,decalare);
return max(x,y);
}
int main()
{
fin >> n >> m;
for(int i=1;i<=n;i++) fin >> a[i];
for(int i=1;i<n;i++){
fin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,1,0);
for(int i=1;i<=nr_lanturi;i++){
decalare[i]=decalare[i-1]+4*lant[i-1].size();
int st=0,dr=lant[i].size()-1;
while(st<dr){
swap(lant[i][st],lant[i][dr]);
pozitia_in_lant[lant[i][st]]=st;
pozitia_in_lant[lant[i][dr]]=dr;
st++;
dr--;
}
pozitia_in_lant[lant[i][st]]=st;
}
for(int i=1;i<=n;i++) update(1,0,lant[ind_lant[i]].size()-1,pozitia_in_lant[i],a[i],decalare[ind_lant[i]]);
for(int i=1;i<=m;i++){
fin >> operatie >> x >> y;
if(operatie==0){
update(1,0,lant[ind_lant[x]].size()-1,pozitia_in_lant[x],y,decalare[ind_lant[x]]);
continue;
}
int rasp=0;
bool ok=true;
while(ok==true){
int lant1=ind_lant[x];
int lant2=ind_lant[y];
if(lant1==lant2){
int poz1=pozitia_in_lant[x];
int poz2=pozitia_in_lant[y];
if(poz1>poz2) swap(poz1,poz2);
rasp=max(rasp,query(1,0,lant[lant1].size()-1,poz1,poz2,decalare[lant1]));
ok=false;
break;
} else if(nivel[parinte_lant[lant1]]>nivel[parinte_lant[lant2]]){
int poz=pozitia_in_lant[x];
rasp=max(rasp,query(1,0,lant[lant1].size()-1,0,poz,decalare[lant1]));
x=parinte_lant[lant1];
} else {
int poz=pozitia_in_lant[y];
rasp=max(rasp,query(1,0,lant[lant2].size()-1,0,poz,decalare[lant2]));
y=parinte_lant[lant2];
}
}
fout << rasp << '\n';
}
return 0;
}