#include <bits/stdc++.h>
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
int n,q,x,y,t,temp;
const int lim=1e5+3;
pair<int,int> arb[19][2*lim];
vector<int> vec[lim];
int poz[lim],cnt;
int lg[2*lim];
int papa[lim];
int val[lim];
int urm[lim];
int dp[lim];
int ad[lim];
bool ok[lim];
void df(int nod,int add)
{
ad[nod]=add;
ok[nod]=true;
int maxim=-1;
poz[nod]=++cnt;
arb[0][cnt]={add,nod};
for(int x:vec[nod])
if(!ok[x])
{
df(x,add+1);
papa[x]=nod;
dp[nod]+=dp[x];
if(dp[x]>maxim)
maxim=dp[x],
urm[nod]=x;
poz[nod]=++cnt;
arb[0][cnt]={add,nod};
}
}
void rmq()
{
for(int i=2;i<=cnt;++i)
lg[i]=lg[i/2]+1;
for(int p=1;p<=lg[cnt];++p)
for(int i=1;i+(1<<p)-1<=cnt;++i)
arb[p][i]=min(arb[p-1][i],arb[p-1][i+(1<<(p-1))]);
}
int lca(int x,int y)
{
x=poz[x],y=poz[y];
if(x>y) swap(x,y);
int d=lg[y-x+1];
return min(arb[d][x],arb[d][y-(1<<d)+1]).second;
}
int unde[lim];
struct path
{
int tata;
vector<int> tree;
vector<int> nodes;
path(int nod)
{
tata=nod;
nodes.clear();
nodes.push_back(0);
}
void init()
{
tree.clear();
tree.resize(4*nodes.size()+3);
}
void build(int nod,int l,int r)
{
if(l==r)
{
tree[nod]=val[nodes[l]];
return ;
}
int med=(l+r)>>1;
build(2*nod,l,med);
build(2*nod+1,med+1,r);
tree[nod]=max(tree[2*nod],tree[2*nod+1]);
}
void update(int nod,int l,int r,int poz,int vxl)
{
if(l==r)
{
tree[nod]=vxl;
return ;
}
int med=(l+r)>>1;
if(poz<=med) update(2*nod,l,med,poz,vxl);
else update(2*nod+1,med+1,r,poz,vxl);
tree[nod]=max(tree[2*nod],tree[2*nod+1]);
}
int query(int nod,int l,int r,int a,int b)
{
if(a<=l and r<=b)
return tree[nod];
int med=(l+r)>>1;
int ans1=0,ans2=0;
if(a<=med) ans1=query(2*nod,l,med,a,b);
if(b>med) ans2=query(2*nod+1,med+1,r,a,b);
return max(ans1,ans2);
}
};
path* buc[lim];
void make(int nod,path* p)
{
buc[nod]=p;
unde[nod]=p->nodes.size();
p->nodes.push_back(nod);
if(urm[nod]==0)
{
p->init();
p->build(1,1,p->nodes.size()-1);
return ;
}
make(urm[nod],p);
for(int x:vec[nod])
if(x!=papa[nod] and x!=urm[nod])
{
buc[x]=new path(x);
make(x,buc[x]);
}
}
int dmax(int jos,int sus)
{
int ans=0;
while(buc[jos]->tata!=buc[sus]->tata)
{
ans=max(ans,buc[jos]->query(1,1,buc[jos]->nodes.size()-1,1,unde[jos]));
jos=papa[buc[jos]->tata];
}
ans=max(ans,buc[jos]->query(1,1,buc[jos]->nodes.size()-1,unde[sus],unde[jos]));
return ans;
}
int main()
{
in>>n>>q;
for(int i=1;i<=n;++i)
in>>val[i];
for(int i=1;i<n;++i)
{
in>>x>>y;
vec[x].push_back(y);
vec[y].push_back(x);
}
buc[1]=new path(1);
df(1,1);
rmq();
make(1,buc[1]);
for(int i=1;i<=q;++i)
{
in>>t>>x>>y;
if(t==0)
buc[x]->update(1,1,buc[x]->nodes.size()-1,unde[x],y);
else temp=lca(x,y),out<<max(dmax(x,temp),dmax(y,temp))<<'\n';
}
return 0;
}