#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
const int dim = 1e5 + 5;
int n,m,v[dim];
vector <int> g[dim],lanturi[dim];
int lant[dim],weight[dim],height[dim],tata_lant[dim],pathgap[dim],cnt_lanturi;
int arb[4*dim],ans;
void DFS(int x,int parent)
{
int ma = 0;
height[x] = height[parent] + 1;
weight[x] = 1;
for (int i=0; i<g[x].size(); i++)
{
int y = g[x][i];
if (y != parent)
{
DFS(y,x);
weight[x] += weight[y];
if (ma == 0 || weight[ma] < weight[y])
{
ma = y;
}
}
}
if (g[x].size() == 1 && x != 1)
{
cnt_lanturi++;
lant[x] = cnt_lanturi;
lanturi[cnt_lanturi].push_back(x);
return ;
}
lant[x] = lant[ma];
lanturi[lant[x]].push_back(x);
for (int i=0; i<g[x].size(); i++)
{
int y = g[x][i];
if (y != parent && y != ma)
{
tata_lant[lant[y]] = x;
}
}
}
void Build(int n,int st,int dr,int gap,int path)
{
if (st == dr)
{
arb[n + gap] = v[lanturi[path][st-1]];
return ;
}
int mid = (st+dr)/2;
Build(2*n,st,mid,gap,path);
Build(2*n+1,mid+1,dr,gap,path);
arb[n+gap] = max(arb[2*n+gap],arb[2*n+1+gap]);
}
void Update(int n,int st,int dr,int pos,int val,int gap)
{
if (st == dr)
{
arb[n + gap] = val;
return ;
}
int mid = (st+dr)/2;
if (pos <= mid)
{
Update(2*n,st,mid,pos,val,gap);
}
else
{
Update(2*n+1,mid+1,dr,pos,val,gap);
}
arb[n+gap] = max(arb[2*n+gap],arb[2*n+1+gap]);
}
void Query(int n,int st,int dr,int lq,int rq,int gap)
{
//if (p == 1) cout << n << " " << st << " " << dr << " " << lq << " " << rq << " " << gap;
if (lq <= st && dr <= rq)
{
ans = max(ans, arb[n+gap]);
return ;
}
int mid = (st+dr)/2;
if (lq <= mid)
{
Query(2*n,st,mid,lq,rq,gap);
}
if (rq >= mid+1)
{
Query(2*n+1,mid+1,dr,lq,rq,gap);
}
}
void Heavypath()
{
DFS(1,0);
for (int i=1; i<=cnt_lanturi; i++)
{
reverse(lanturi[i].begin(), lanturi[i].end());
if (i > 1)
{
pathgap[i] = pathgap[i-1] + 4*lanturi[i-1].size();
}
Build(1,1,lanturi[i].size(), pathgap[i], i);
}
}
int main()
{
in >> n >> m;
for (int i=1; i<=n; i++)
{
in >> v[i];
}
for (int i=1; i<n; i++)
{
int x,y;
in >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
Heavypath();
/// cout << tata_lant[lant[6]];
/// cout << lant[6];
while (m--)
{
int x,y,t;
in >> t >> x >> y;
/// cout << x << " " << y << " " << lant[x] << " " << lant[y] << "\n";
if (t == 0)
{
v[x] = y;
Update(1,1,lanturi[lant[x]].size(), height[x] - height[tata_lant[lant[x]]], y, pathgap[lant[x]]);
}
else
{
ans = 0;
while (1)
{
///cout << x << " " << y << "\n";
if (lant[x] == lant[y])
{
if (height[x] > height[y]) swap(x,y);
///cout << lanturi[ lant[x] ].size() << "\n";
Query(1,1,lanturi[ lant[x] ].size(),height[x] - height[tata_lant[lant[x]]],height[y] - height[tata_lant[lant[y]]], pathgap[lant[x]]);
break;
}
if (height[tata_lant[lant[x]]] < height[tata_lant[lant[y]]]) swap(x,y);
Query(1,1,lanturi[ lant[x] ].size(),1,height[x] - height[tata_lant[lant[x]]], pathgap[lant[x]]);
x = tata_lant[lant[x]];
}
out << ans << "\n";
}
}
return 0;
}