#include<bits/stdc++.h>
#define debug(x) cerr << #x << " " << x << "\n"
#define debugs(x) cerr << #x << " " << x << " "
#pragma GCC optimize("Ofast")
#define int long long
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int range_rng(int l, int r)
{
return uniform_int_distribution<int>(l,r)(rng);
}
int v[100005];
int stamp[100005];
int cv[100005];
vector<int> nodes[100005];
int h[100005];
int p[100005];
int heavychild[100005];
int sz[100005];
int pathend[100005];
int timer;
class AINT
{
public:
int aint[400005];
void build(int l, int r, int val)
{
if (l==r)
{
aint[val]=v[l];
return;
}
int mid;
mid=(l+r)/2;
build(l,mid,val*2);
build(mid+1,r,val*2+1);
aint[val]=max(aint[val*2],aint[val*2+1]);
}
void update(int l, int r, int val, int poz, int x)
{
if (l==r)
{
v[l]=x;
aint[val]=v[l];
return;
}
int mid;
mid=(l+r)/2;
if (poz<=mid)
update(l,mid,val*2,poz,x);
else
update(mid+1,r,val*2+1,poz,x);
aint[val]=max(aint[val*2],aint[val*2+1]);
}
int query(int l, int r, int val, int qa, int qb)
{
if (qa<=l && r<=qb)
{
return aint[val];
}
int mid,ans;
ans=-1;
mid=(l+r)/2;
if (qa<=mid)
ans=max(ans,query(l,mid,val*2,qa,qb));
if (qb>mid)
ans=max(ans,query(mid+1,r,val*2+1,qa,qb));
return ans;
}
void update(int node, int val)
{
update(1,timer,1,stamp[node],val);
}
int query(int u, int v)
{
int ans;
ans=-1;
while (pathend[u]!=pathend[v])
{
if (h[pathend[u]]<h[pathend[v]])
swap(u,v);
ans=max(ans,query(1,timer,1,stamp[pathend[u]],stamp[u]));
u=p[pathend[u]];
}
if (stamp[u]>stamp[v])
swap(u,v);
ans=max(ans,query(1,timer,1,stamp[u],stamp[v]));
return ans;
}
} aint;
void dfs(int node, int parent)
{
int mx;
mx=0;
p[node]=parent;
sz[node]=1;
for (auto x : nodes[node])
{
if (x!=parent)
{
h[x]=h[node]+1;
dfs(x,node);
sz[node]+=sz[x];
if (sz[x]>sz[mx])
mx=x;
}
}
heavychild[node]=mx;
}
void heavyfirst(int node, int parent, int capat)
{
stamp[node]=++timer;
v[timer]=cv[node];
pathend[node]=capat;
if (heavychild[node]==0)
return;
heavyfirst(heavychild[node],node,capat);
for (auto x : nodes[node])
{
if (x!=parent && x!=heavychild[node])
{
heavyfirst(x,node,x);
}
}
}
signed main()
{
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,m,i,j,x,y,type;
fin >> n >> m;
for (i=1; i<=n; i++)
{
fin >> cv[i];
}
for (i=1; i<=n-1; i++)
{
fin >> x >> y;
nodes[x].push_back(y);
nodes[y].push_back(x);
}
h[1]=1;
dfs(1,0);
timer=0;
heavyfirst(1,0,1);
aint.build(1,timer,1);
for (i=1; i<=m; i++)
{
fin >> type;
if (type==0)
{
fin >> x >> y;
aint.update(x,y);
}
else
{
fin >> x >> y;
fout << aint.query(x,y) << "\n";
}
}
return 0;
}