#include <fstream>
#include <vector>
#include <bitset>
#define DIM 100011
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int n,m,k,z;
int p[2*DIM]; //puterile lui 2 asociate fiecarei pozitie
int F[DIM]; //prima aparitie a unui nod in parcurgerea Euler
int poz[DIM]; //lantul din care face parte un nod
int nr[20011]; //cate noduri are fiecare lant
int nr1[DIM];//cate noduri are fiecare fiu in subarborele sau
int loc[DIM]; //pozitia unui nod in lantul din care face parte
int T[DIM]; //tatal unui nod
int a[20][2*DIM]; //matricea RMQ
long long V[DIM]; //valuarea unui nod
pair<int,int> E[2*DIM]; //vectorul corespunzator parcurgerii euler <nod,nivel>
vector<int> L[DIM];//liste de vecini
vector<int> LT[20011];//liste de lanturi
vector<int> A[20011];//arborii de intervale asociati lanturilor
bitset<DIM> viz;
void dfs(int nod,int niv,int tata){
vector<int>::iterator it;
int maxim=0,pz;
viz[nod]=1;
nr1[nod]=1;
T[nod]=tata;
E[++k]=make_pair(nod,niv);
if(!F[nod]) F[nod]=k;
if(L[nod].size()==1 && nod!=1){
LT[++z].push_back(0);
LT[z].push_back(nod);
poz[nod]=z;
nr[z]=1;
return;
}
for(it=L[nod].begin();it!=L[nod].end();it++){
if(viz[*it]) continue;
dfs(*it,niv+1,nod);
nr1[nod]+=nr1[*it];
E[++k]=make_pair(nod,niv);
if(nr1[*it]>maxim)
maxim=nr1[*it],pz=poz[*it];
}
nr[pz]++;
LT[pz].push_back(nod);
poz[nod]=pz;
}
void build(int i,int nod,int p,int u){
if(p==u){
A[i][nod]=LT[i][p];
return;
}
int mid=p+(u-p)/2;
build(i,2*nod,p,mid);
build(i,2*nod+1,mid+1,u);
//A[i][nod]=max(A[i][2*nod],A[i][2*nod+1]);
if(V[A[i][2*nod]]>V[A[i][2*nod+1]])
A[i][nod]=A[i][2*nod];
else
A[i][nod]=A[i][2*nod+1];
}
void update(int i,int nod,int p,int u,int a,int b){
if(p==u)
return;
int mid=p+(u-p)/2;
if(a<=mid)
update(i,2*nod,p,mid,a,b);
else
update(i,2*nod+1,mid+1,u,a,b);
if(V[A[i][2*nod]]>V[A[i][2*nod+1]])
A[i][nod]=A[i][2*nod];
else
A[i][nod]=A[i][2*nod+1];
}
int query(int i,int nod,int p,int u,int a,int b){
if(a<=p && u<=b){
return A[i][nod];
}
int mid=p+(u-p)/2,st=0,dr=0;
if(a<=mid)
st=query(i,2*nod,p,mid,a,b);
if(b>mid)
dr=query(i,2*nod+1,mid+1,u,a,b);
if(V[st]>V[dr])
return st;
else
return dr;
}
int main(void){
register int q,q1,q2,i,j,x,y,jv,b,t,x1,y1,LCA;
f>>n>>m;
for(i=1;i<=n;i++) f>>V[i];
for(i=1;i<n;i++){
f>>x>>y;
L[x].push_back(y);
L[y].push_back(x);
}
dfs(1,1,0);
//sortam lanturile
for(t=1;t<=z;t++){
for(i=1,j=nr[t];i<=j;i++,j--)
swap(LT[t][i],LT[t][j]),loc[LT[t][i]]=i,loc[LT[t][j]]=j;
}
a[0][1]=1;
for(i=2;i<=k;i++) p[i]=1+p[i/2],a[0][i]=i;
for(i=1;(1<<i)<=k;i++){
for(j=1;j<=k;j++){
a[i][j]=a[i-1][j],jv=((1<<(i-1))+j);
if(jv<=k && E[a[i][j]].second>=E[a[i-1][jv]].second)
a[i][j]=a[i-1][jv];
}
}
for(i=1;i<=z;i++){
A[i].assign(4*(nr[i])+11,0);
build(i,1,1,nr[i]);
}
for(i=1;i<=m;i++){
f>>t>>x>>y;
if(t==1){
//x1=LT[poz[x]][nr[poz[x]]];
//y1=LT[poz[y]][nr[poz[y]]];
x1=F[x],y1=F[y];
if(x1>y1) swap(x1,y1);
b=p[y1-x1+1];
jv=(y1-(1<<b)+1);
if(E[a[b][x1]].second<=E[a[b][jv]].second)
LCA=E[a[b][x1]].first;
else LCA=E[a[b][jv]].first;
if(poz[x]==poz[y]){
q1=query(poz[x],1,1,nr[poz[x]],min(loc[x],loc[y]),max(loc[x],loc[y]));
g<<V[q1]<<"\n";
continue;
}
q1=q2=0;
while(poz[x]!=poz[LCA]){
q=query(poz[x],1,1,nr[poz[x]],1,loc[x]);
if(V[q1]<V[q]) q1=q;
x=T[LT[poz[x]][1]];
}
q=query(poz[x],1,1,nr[poz[x]],min(loc[x],loc[LCA]),max(loc[x],loc[LCA]));
if(V[q1]<V[q]) q1=q;
while(poz[y]!=poz[LCA]){
q=query(poz[y],1,1,nr[poz[y]],1,loc[y]);
if(V[q2]<V[q]) q2=q;
y=T[LT[poz[y]][1]];
}
q=query(poz[y],1,1,nr[poz[y]],min(loc[y],loc[LCA]),max(loc[y],loc[LCA]));
if(V[q2]<V[q]) q2=q;
g<<max(V[q1],V[q2])<<"\n";
}
else{
V[x]=y;
update(poz[x],1,1,nr[poz[x]],loc[x],y);
}
}
f.close();
g.close();
return 0;
}