#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int N,M;
vector <int> G[100005];
vector <int> P[100005];
int Value[100005];
int Arb[4*100005];
int Poz[100005];
int Heavy[100005],L[100005],nbL,Father[100005],LNiv[100005],Level[100005];
void Read()
{
int i;
f>>N>>M;
for(int i=1;i<=N;i++)
f>>Value[i];
for(i=1;i<=M;i++)
{
int x,y;
f>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
}
void DFS(int node,int father)
{
bool leaf=1;
Heavy[node]=1;
int poz=-1;
for(int i=0;i<G[node].size();i++)
{
int neighb=G[node][i];
if(neighb==father)
continue;
Level[neighb]=Level[node]+1;
leaf=0;
DFS(neighb,node);
Heavy[node]+=Heavy[neighb];
if(poz==-1)
poz=neighb;
else
if(Heavy[poz]<Heavy[neighb])
poz=neighb;
}
if(leaf==1)
{
L[node]=++nbL;
P[nbL].push_back(node);
return;
}
L[node]=L[poz];
P[L[poz]].push_back(node);
for(int i=0;i<G[node].size();i++)
{
int neighb=G[node][i];
if(neighb==father || neighb==poz)
continue;
Father[L[neighb]]=node;
LNiv[L[neighb]]=Level[node];
}
}
void Build(int K,int A,int B,int dec,int chain)
{
if(A>B)
return;
if(A==B)
{
Arb[K+dec]=Value[P[chain][A-1]];
return;
}
Build(2*K,A,(A+B)/2,dec,chain);
Build(2*K+1,(A+B)/2+1,B,dec,chain);
Arb[K+dec]=max(Arb[2*K+dec],Arb[2*K+1+dec]);
}
void Update(int K,int A,int B,int dec,int poz,int val)
{
if(A>B || A>poz || B<poz)
return;
if(A==B)
{
Arb[K+dec]=val;
return;
}
Update(2*K,A,(A+B)/2,dec,poz,val);
Update(2*K+1,(A+B)/2+1,B,dec,poz,val);
Arb[K+dec]=max(Arb[2*K+dec],Arb[2*K+1+dec]);
}
int Query(int K,int A,int B,int dec,int poz,int poz2)
{
if(A>B || A>poz2 || B<poz)
return 0;
if(poz<=A && B<=poz2)
{
return Arb[K+dec];
}
return (max(Query(2*K,A,(A+B)/2,dec,poz,poz2),Query(2*K+1,(A+B)/2+1,B,dec,poz,poz2)));
}
void Browse()
{
int i;
for(i=1;i<=M;i++)
{
int type,x,y;
f>>type>>x>>y;
if(type==0)
Update(1,1,P[L[x]].size(),Poz[L[x]],Level[x]-LNiv[L[x]],y);
else
{
int Max=0;
while(1)
{
if(L[x]==L[y])
{
if(Level[x]>Level[y])
swap(x,y);
g<<max(Max,Query(1,1,P[L[x]].size(),Poz[L[x]],Level[x]-LNiv[L[x]],Level[y]-LNiv[L[x]]))<<"\n";
break;
}
else
{
if(LNiv[x]>LNiv[y])
swap(x,y);
Max=max(Max,Query(1,1,P[L[x]].size(),1,Poz[L[x]],Level[x]-LNiv[x]));
x=Father[L[x]];
}
}
}
}
}
void Path()
{
Level[1]=1;
DFS(1,0);
for(int i=1;i<=nbL;i++)
{
reverse(P[i].begin(),P[i].end());
if(i>1)
Poz[i]=Poz[i-1]+4*P[i].size();
Build(1,1,P[i].size(),Poz[i],i);
}
}
int main()
{
Read();
Path();
Browse();
return 0;
}