#include<fstream>
#include<vector>
#define NMAX 100005
#define VEC p->val
#define son (nod<<1)
#define middle ((left+right)>>1)
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
struct Nod
{
Nod *prev;
int val;
}*G[NMAX],*split[NMAX];
vector<int> size;
int level[NMAX],TT[NMAX],what[NMAX],lant[NMAX],under[NMAX],vect[NMAX];
int *AINT,Maxx,K,L,R,poz,val;
int n,Q,v[NMAX],k,TT_lant[NMAX];
void add(Nod *&x,int val)
{
Nod *p=new Nod;
p->val=val;
p->prev=x;
x=p;
}
void clear(Nod *&x)
{
if(!x)
return;
for(Nod *p;x;x=p)
{
p=x->prev;
delete x;
}
}
void read()
{
size.resize(NMAX,0);
fin>>n>>Q;
for(int i=1;i<=n;i++)
fin>>v[i];
for(int i=1,x,y;i<n;i++)
{
fin>>x>>y;
size[x]++;
size[y]++;
add(G[x],y);
add(G[y],x);
}
}
inline void DFS(int nod,int tt)
{
int maxim=-1;
TT[nod]=tt;
level[nod]=level[tt]+1;
if(size[nod]==1 && nod!=1)
{
lant[nod]=++k;
add(split[k],nod);
return;
}
for(Nod *p=G[nod];p;p=p->prev)
if(VEC!=tt)
{
DFS(VEC,nod);
under[nod]+=under[VEC]+1;
if(maxim<under[VEC])
{
maxim=under[VEC];
lant[nod]=lant[VEC];
}
}
add(split[lant[nod]],nod);
}
void update(int left,int right,int nod)
{
nod=vect[poz];
AINT[nod]=val;
for(nod>>=1;nod;nod>>=1)
AINT[nod]=max(AINT[son],AINT[son+1]);
}
void build_AINT(int left,int right,int nod)
{
if(left==right)
{
AINT[nod]=vect[left];
vect[left]=nod;
return;
}
build_AINT(left,middle,son);
build_AINT(middle+1,right,son+1);
AINT[nod]=max(AINT[son],AINT[son+1]);
}
inline void query(int left,int right,int nod)
{
if(left>R || right<L)
return;
if(L<=left && right<=R)
{
Maxx=max(Maxx,AINT[nod]);
return;
}
query(left,middle,son);
query(middle+1,right,son+1);
}
void group_init()
{
for(int i=1,L=1;i<=k;i++)
{
TT_lant[i]=split[i]->val;
for(Nod *p=split[i];p;p=p->prev,L++)
{
what[ p->val ]=L;
vect[L]=v[p->val];
}
clear(split[i]);
}
AINT=new int[(1<<18)];
build_AINT(1,n,1);
}
void prep()
{
DFS(1,0);
for(int i=1;i<=n;i++)
clear(G[i]);
size.clear();
group_init();
}
int LCA(int x,int y)
{
while(lant[x]!=lant[y])
{
if(level[TT_lant[lant[x]]]>level[TT_lant[lant[y]]])
{
x=TT[TT_lant[lant[x]]];
continue;
}
if(level[TT_lant[lant[x]]]<level[TT_lant[lant[y]]])
{
y=TT[TT_lant[lant[y]]];
continue;
}
x=TT[TT_lant[lant[x]]];
y=TT[TT_lant[lant[y]]];
}
if(level[x]>level[y])
return y;
else
return x;
}
void Val(int x,int lca,int &sol)
{
while(level[x]>level[lca])
{
Maxx=0;
R=what[x];
if(lant[x]==lant[lca])
L=what[lca];
else
L=what[TT_lant[lant[x]]];
query(1,n,1);
sol=max(sol,Maxx);
x=TT[TT_lant[lant[x]]];
}
sol=max(sol,v[lca]);
}
int main()
{
read();
prep();
for(int op,x,y,lca,sol;Q;Q--)
{
fin>>op>>x>>y;
if(!op)
{
val=v[x]=y;
poz=what[x];
update(1,n,1);
continue;
}
sol=0;
lca=LCA(x,y);
Val(x,lca,sol);
Val(y,lca,sol);
fout<<sol<<'\n';
}
return 0;
}