#include<bits/stdc++.h>
#define N 100030
#define L (nod<<1)
#define R (L|1)
using namespace std;
int n,m;
vector<int>V[N];
int sz[N], lant[N], p[N], cnt[N], ord[N], bgn[N], lvl[N];
int nrlant,k, h[4*N], a[N];
//p parinte lant, ord nr ordine in land, cnt 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)>>1;
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)>>1;
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);
}
void DFS(int x, int pr) {
sz[x]=1;
for (auto it:V[x]) {
if (it!=pr) DFS(it, x), sz[x]+=sz[it];
}
}
void HLD(int x, int pr, int depth) {
int bigC=-1, mx=-1;
lant[x]=nrlant;
ord[x]=++cnt[nrlant];
for (auto it:V[x])
if (it!=pr && sz[it]>mx) mx=sz[it], bigC=it;
if (bigC!=-1) HLD(bigC,x,depth);
for (auto it:V[x]) {
if (it!=pr && it!=bigC) {
p[++nrlant]=x;
lvl[nrlant]=depth+1;
HLD(it, x, depth+1);
}
}
if (ord[x]==cnt[lant[x]]) bgn[lant[x]]=k+1, k+=cnt[lant[x]];
update(1,n,1,bgn[lant[x]]+ord[x]-1, a[x]);
}
int main() {
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
cin>>n>>m;
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);
HLD(1,-1,0);
for (int i=1; i<=m; ++i) {
int c,x,y; cin>>c>>x>>y;
if (!c) update(1,n,1,bgn[lant[x]]+ord[x]-1,y);
else {
int mx=0;
while (lant[x]!=lant[y]) {
if (lvl[lant[x]]<lvl[lant[y]]) swap(x,y);
mx=max(mx, query(1,n,1, bgn[lant[x]], bgn[lant[x]]+ord[x]-1));
x=p[lant[x]];
}
if (ord[x]>ord[y]) swap(x,y);
mx=max(mx, query(1,n,1, bgn[lant[x]]+ord[x]-1, bgn[lant[x]]+ord[y]-1));
cout<<mx<<'\n';
}
}
return 0;
}