#include<fstream>
#include<iostream>
#include<vector>
#include<algorithm>
#define MAXN 100010
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
vector <int> Muchie[MAXN],LantElementar[MAXN];
int N,M,Valoare[MAXN];
int viz[MAXN],fii[MAXN],nivel[MAXN],lant[MAXN];
int NumarSiruri,tata[MAXN],ArbInt[4*MAXN],poz[MAXN];
void Citire_Graf() {
int i,x,y;
in>>N>>M;
for(i=1;i<=N;i++)
in>>Valoare[i];
for(i=1;i<=N-1;i++) {
in>>x>>y;
Muchie[x].push_back(y);
Muchie[y].push_back(x);
}
}
void dfs(int nod) {
int i,vecin,best=-1;
viz[nod]=1;
fii[nod]=1;
for(i=0;i<Muchie[nod].size();i++) {
vecin=Muchie[nod][i];
if(viz[vecin]==0) {
nivel[vecin]=nivel[nod]+1;
dfs(vecin);
fii[nod]+=fii[vecin];
if(best==-1 || fii[best]<fii[vecin])
best=vecin;
}
}
if(fii[nod]==1) {
NumarSiruri++;
lant[nod]=NumarSiruri;
LantElementar[NumarSiruri].push_back(nod);
return;
}
lant[nod]=lant[best];
LantElementar[lant[nod]].push_back(nod);
for(i=0;i<Muchie[nod].size();i++){
vecin=Muchie[nod][i];
if(vecin!=best)
tata[lant[vecin]]=nod;
}
}
void Construire(int nod,int st,int dr,int lant,int decalaj) {
int mij;
if(st==dr) {
ArbInt[nod+decalaj]=Valoare[LantElementar[lant][st-1]];
return;
}
mij=(st+dr)/2;
Construire(2*nod,st,mij,lant,decalaj);
Construire(2*nod+1,mij+1,dr,lant,decalaj);
ArbInt[nod+decalaj]=max(ArbInt[2*nod+decalaj],ArbInt[2*nod+1+decalaj]);
}
void Creere_Drumuri() {
int i;
nivel[1]=1;
dfs(1);
for(i=1;i<=NumarSiruri;i++) {
reverse(LantElementar[i].begin(),LantElementar[i].end());
poz[i]=poz[i-1]+(LantElementar[i-1].size()*4);
Construire(1,1,LantElementar[i].size(),i,poz[i]);
}
}
void Initializare() {
Citire_Graf();
Creere_Drumuri();
}
void Actualizare(int nod,int st,int dr,int val,int poz,int decalaj) {
int mij;
if(st==dr){
ArbInt[nod+decalaj]=val;
return ;
}
mij=(st+dr)/2;
if(poz<=mij)
Actualizare(2*nod,st,mij,val,poz,decalaj);
else
Actualizare(2*nod+1,mij+1,dr,val,poz,decalaj);
ArbInt[nod+decalaj]=max(ArbInt[2*nod+decalaj],ArbInt[2*nod+1+decalaj]);
}
int interogare (int nod,int st,int dr,int a,int b,int decalaj) {
int mij,partial=0;
if(a<=st&&dr<=b)
return ArbInt[nod+decalaj];
mij=(st+dr)/2;
if(a<=mij)
partial=interogare(2*nod,st,mij,a,b,decalaj);
if(b>mij)
partial=max(partial,interogare(2*nod+1,mij+1,dr,a,b,decalaj));
return partial;
}
int MaxLant(int x,int y) {
int sol;
sol=0;
while(lant[x]!=lant[y]) {
if(nivel[tata[lant[x]]]<nivel[tata[lant[y]]])
swap(x,y);
sol=max(sol,interogare(1,1,LantElementar[lant[x]].size(),1,nivel[x]-nivel[tata[lant[x]]],poz[lant[x]]));
x=tata[lant[x]];
}
if(nivel[x]>nivel[y])
swap(x,y);
sol=max(sol,interogare(1,1,LantElementar[lant[x]].size(),nivel[x]-nivel[tata[lant[x]]],nivel[y]-nivel[tata[lant[y]]], poz[lant[x]] ));
return sol;
}
void Solve() {
int i,tip,x,y;
for(i=1;i<=M;i++) {
in>>tip>>x>>y;
if(tip==0){
Actualizare(1,1,LantElementar[lant[x]].size(),y,nivel[x]-nivel[tata[lant[x]]],poz[lant[x]]);
}
if(tip==1){
out<<MaxLant(x,y)<<'\n';
}
}
in.close();
out.close();
}
int main() {
Initializare();
Solve();
return 0;
}