#include <fstream>
#include <algorithm>
#include <vector>
#define nmax 100100
#define Vecin G[Nod][i]
#define Position(x) (Level[x]-Level[Father[Lant[x]]])
using namespace std;
vector <int> G[nmax],LantElementar[nmax];
int N,Q,Value[nmax],Level[nmax],Fii[nmax],Lant[nmax];
int NrLant,Father[nmax],Start[nmax],Ai[4*nmax];
bool used[nmax];
void Update(int Nod,int Left,int Right,int X,int Decalaj,int value) {
if(Left == Right) {
Ai[Nod+Decalaj]=value;
return;
}
int Mid=(Left+Right)>>1;
if(X<=Mid) Update(Nod<<1,Left,Mid,X,Decalaj,value);
else Update((Nod<<1)|1,Mid+1,Right,X,Decalaj,value);
Ai[Nod+Decalaj]=max(Ai[(Nod<<1)+Decalaj],Ai[((Nod<<1)|1)+Decalaj]);
}
int Query(int Nod,int Left,int Right,int A,int B,int Decalaj) {
if(A <= Left && Right <= B)
return Ai[Nod+Decalaj];
int Mid=(Left+Right)>>1,Answer=0;
if(A<=Mid) Answer = Query(Nod<<1,Left,Mid,A,B,Decalaj);
if(B>Mid) Answer = max (Answer, Query((Nod<<1)|1,Mid+1,Right,A,B,Decalaj));
return Answer;
}
void Build(int Nod,int Left,int Right,int Decalaj,int lant) {
if(Left == Right) {
Ai[Nod+Decalaj]=Value[ LantElementar[lant][Left-1] ];
return;
}
int Mid=(Left+Right)>>1;
Build(Nod<<1,Left,Mid,Decalaj,lant);
Build((Nod<<1)|1,Mid+1,Right,Decalaj,lant);
Ai[Nod+Decalaj]=max(Ai[(Nod<<1)+Decalaj],Ai[((Nod<<1)|1)+Decalaj]);
}
void Dfs(int Nod) {
int i,Fiu=0;
used[Nod]=1;
for(i=0;i<G[Nod].size();i++)
if(!used[Vecin]) {
Level[Vecin]=Level[Nod]+1;
Dfs(Vecin);
Fii[Nod]+=Fii[Vecin]+1;
if(!Fiu || Fii[Fiu]<Fii[Vecin])
Fiu=Vecin;
}
if(!Fii[Nod]) {
Lant[Nod]=++NrLant;
LantElementar[NrLant].push_back(Nod);
return;
}
Lant[Nod]=Lant[Fiu];
LantElementar[Lant[Nod]].push_back(Nod);
for(i=0;i<G[Nod].size();i++)
if(Vecin != Fiu && Level[Vecin] > Level[Nod])
Father[ Lant[Vecin] ] = Nod;
}
void BuildPaths() {
Level[1]=1;
Dfs(1);
for(int i=1;i<=NrLant;i++) {
reverse(LantElementar[i].begin(),LantElementar[i].end());
Start[i] = Start[i-1] + 4*LantElementar[i-1].size();
Build(1,1,LantElementar[i].size(),Start[i],i);
}
}
void read(ifstream & in) {
int i,x,y;
in>>N>>Q;
for(i=1;i<=N;i++)
in>>Value[i];
for(i=1;i<N;i++) {
in>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
}
int main() {
int tip,x,y,lant,Answer;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
read(in);
BuildPaths();
while(Q--) {
in>>tip>>x>>y;
if(tip == 0) {
lant=Lant[x];
Update(1,1,LantElementar[lant].size(),Position(x),Start[lant],y);
}
else {
Answer=0;
while( Lant[x] != Lant[y] ) {
if(Level[Father[Lant[x]]] < Level[Father[Lant[y]]])
swap(x,y);
lant=Lant[x];
Answer = max(Answer, Query(1,1,LantElementar[lant].size(),1,Position(x),Start[lant]));
x = Father[lant];
}
lant = Lant[x];
if(Level[x] > Level[y])
swap(x,y);
Answer = max(Answer, Query(1,1,LantElementar[lant].size(),Position(x),Position(y),Start[lant]));
out<<Answer<<'\n';
}
}
in.close();
out.close();
return 0;
}