#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream in ("heavypath.in");
ofstream out("heavypath.out");
int n, qq, x, y, mom, tip;
vector <vector <int> > vecini;
vector <int> visIn; ///momentul vizitei initiale
vector <int> order; ///ordinea in care apar elementele in parcurgerea dfs2
vector <int> depth; ///adancimile nodurilor
vector <int> vals; ///valorile nodurilor (initiale)
vector <int> seg; ///segtree-ul
vector <int> component; ///capul lantului
vector <int> father; ///tatal fiecarui nod
vector <int> subSum; ///numarul de elemente din subarbore
void getReadingDone();
void getHLDBuilt();
void dfs1(int nod, int dad, int level);
void dfs2(int nod);
void buildSeg(int st=0, int dr=n-1, int poz=0);
void update(int pozQQ, int val, int st=0, int dr=n-1, int poz=0);
int query(int stQQ, int drQQ, int st=0, int dr=n-1, int poz=0);
inline int queryPath(int x, int y){
int maxx=0;
while(component[x]!=component[y]){
if(depth[component[x]]<depth[component[y]])
swap(x, y);
maxx=max(maxx, query(visIn[component[x]], visIn[x]));
x=father[component[x]];
}
if(depth[x]>depth[y])
swap(x, y);
maxx=max(maxx, query(visIn[x], visIn[y]));
return maxx;
}
int main()
{
getReadingDone();
getHLDBuilt();
while(qq--){
in>>tip>>x>>y;
if(tip==0){
update(visIn[x], y);
}
else {
out<<queryPath(x, y)<<"\n";
}
}
return 0;
}
inline void getReadingDone(){
in>>n>>qq;
vals.resize(n+1);
vecini.resize(n+1);
for(int i=1; i<=n ; i++){
in>>vals[i];
}
for(int i=1; i<n; i++){
in>>x>>y;
vecini[x].push_back(y);
vecini[y].push_back(x);
}
}
inline void getHLDBuilt(){
subSum.resize(n+1);
father.resize(n+1);
depth.resize(n+1);
dfs1(1, 0, 1);
mom=0;
order.resize(n+1);
visIn.resize(n+1);
component.resize(n+1);
component[1]=1;
dfs2(1);
seg.resize(2*n+1);
buildSeg();
}
void dfs1(int nod, int dad, int level){
depth[nod]=level;
father[nod]=dad;
subSum[nod]=1;
for(unsigned i=0; i<vecini[nod].size(); i++)
if(vecini[nod][i]!=dad){
dfs1(vecini[nod][i], nod, level+1);
subSum[nod]+=subSum[vecini[nod][i]];
if(subSum[vecini[nod][i]]>subSum[vecini[nod][0]]||vecini[nod][0]==dad)
swap(vecini[nod][i], vecini[nod][0]);
}
}
void dfs2(int nod){
visIn[nod]=mom;
order[mom]=nod;
mom++;
for(unsigned i=0; i<vecini[nod].size(); i++)
if(vecini[nod][i]!=father[nod]){
component[vecini[nod][i]]=(vecini[nod][i]==vecini[nod][0])? component[nod] : vecini[nod][i];
dfs2(vecini[nod][i]);
}
}
void buildSeg(int st, int dr, int poz){
if(st==dr){
seg[poz]=vals[order[st]];
return;
}
int mij=(st+dr)/2;
buildSeg(st, mij, poz+1);
buildSeg(mij+1, dr, poz+2*(mij-st+1));
seg[poz]=max(seg[poz+1], seg[poz+2*(mij-st+1)]);
}
void update(int pozQQ, int val, int st, int dr, int poz){
if(st==dr){
seg[poz]=val;
return;
}
int mij=(st+dr)/2;
if(pozQQ<=mij)
update(pozQQ, val, st, mij, poz+1);
else
update(pozQQ, val, mij+1, dr, poz+2*(mij-st+1));
seg[poz]=max(seg[poz+1], seg[poz+2*(mij-st+1)]);
}
int query(int stQQ, int drQQ, int st, int dr, int poz){
if(stQQ<=st&&dr<=drQQ)
return seg[poz];
int mij=(st+dr)/2;
if(stQQ<=mij&&mij+1<=drQQ)
return max(query(stQQ, drQQ, st, mij, poz+1), query(stQQ, drQQ, mij+1, dr, poz+2*(mij-st+1)) );
else if (stQQ<=mij)
return query(stQQ, drQQ, st, mij, poz+1);
else if(mij+1<=drQQ)
return query(stQQ, drQQ, mij+1, dr, poz+2*(mij-st+1));
}