#include<bits/stdc++.h>
#define N 100010
#define L 2*nod
#define R L|1
using namespace std;
vector<int>V[N];
int a[N], mxc[N], dif[N],k;
int lant,idx[N], lvl[N],cnt[N], ord[N];
int h[N], p[N];
int n,q; //idx lant //cnt-nr elem in lant
void update(int st, int dr, int nod, int idx, int val) {
if (st==dr) {
h[nod]=val;
return;
}
int mid=(st+dr)/2;
if (idx<=mid) update(st,mid,L,idx,val);
else update(mid+1,dr,R,idx,val);
h[nod]=max(h[L], h[R]);
}
int query(int st, int dr, int nod, int l, int r) {
if (l<=st && dr<=r) {
return h[nod];
}
int mid=(st+dr)/2;
int left=0, right=0;
if (l<=mid) left=query(st ,mid,L,l,r);
if (r>mid) {
right=query(mid+1,dr,R,l,r);
}
return max(left, right);
}
int DFS(int x, int pr) {
int s=0,mxs=0,p=0;
for (auto it:V[x]) {
if (it!=pr) {
int y=DFS(it,x);
s+=y;
if (y>mxs) p=it,mxs=y;
}
}
mxc[x]=p;
return s+1;
}
void DFS2(int x, int pr, int c, int h) {//c-idx lant
idx[x]=c; cnt[c]++; ++k;
if (idx[pr]==c) ord[x]=ord[pr]+1;
else ord[x]=1;
if (mxc[x]) DFS2(mxc[x],x,c,h);
for (auto it:V[x]) {
if (it!=pr && it!=mxc[x]) {
p[++lant]=x; lvl[lant]=h+1;
DFS2(it,x, lant,h+1);
}
}
if (V[x].size()==1 && (x!=1||n==1)) dif[c]=k-cnt[c]+1;
update(1,n,1, dif[c]+ord[x]-1, a[x]);
}
int main() {
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
cin>>n>>q;
for (int i=1; i<=n; ++i) cin>>a[i];
for (int i=1; i<n; ++i) {
int x,y; cin>>x>>y;
V[x].push_back(y);
V[y].push_back(x);
}
DFS(1,-1);
DFS2(1,-1,++lant,0);
while (q--) {
int c,x,y; cin>>c>>x>>y;
if (!c) {
update(1,n,1,dif[idx[x]]+ord[x]-1, y);
} else {
int rs=0;
while (!(lvl[idx[x]]==lvl[idx[y]] && idx[x]==idx[y])) {
if (lvl[idx[x]]<lvl[idx[y]]) swap(x,y);
int idxx=idx[x], idxy=idx[y];
rs=max(rs, query(1,n,1,dif[idxx], dif[idxx]+ord[x]-1));
x=p[idxx];
}
if (ord[x]>ord[y]) swap(x,y);
rs=max(rs,query(1,n,1,dif[idx[x]]+ord[x]-1, dif[idx[x]]+ord[y]-1));
cout<<rs<<'\n';
}
}
return 0;
}