#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
vector<int>g[100001], p[100001];
int w[100001], niv[100001], where[100001], n, m, x, y, num_paths=1, Parent[100001], v[100001];
int arb[100001*4], sol, poz[100001], op;
bool used[100001], is_free[100001];
bool cmp(int a, int b){
return w[a] > w[b];
}
void Dfs(int x)
{
used[x]=1;
w[x]=1;
for(vector<int>::iterator it=g[x].begin(); it<g[x].end(); it++ )
if(!used[*it])
{
niv[*it]=niv[x]+1;
Dfs(*it);
w[x]+=w[*it];
}
}
void Update(int nod, int left, int right, int pos, int val, int decalaj)
{
if(left==right)
{
arb[nod+decalaj]=val;
return;
}
int mid = (left+right)/2;
if ( pos <= mid)
Update(2*nod,left,mid,pos,val,decalaj);
else
Update(2*nod+1,mid+1,right,pos,val,decalaj);
arb[nod+decalaj]=max(arb[2*nod+1+decalaj],arb[2*nod+decalaj]);
}
int query(int nod, int left, int right, int qleft, int qright, int decalaj)
{
if(qleft <= left && right <= qright)
return arb[nod + decalaj];
int mid = (left+right)/2, rez = 0;
if(qleft <= mid)
rez = max(rez, query(nod * 2, left, mid, qleft, qright, decalaj));
if(mid < qright)
rez = max(rez, query(nod * 2 + 1, mid + 1, right, qleft, qright, decalaj));
return rez;
}
void Heavy_Path(int x, int path)
{
used[x]=1;
where[x]=path;
p[path].push_back(x);
for(vector<int>::iterator it=g[x].begin(); it<g[x].end(); it++ )
if(!used[*it])
{
if(!is_free[x])
{
is_free[x]=1;
Heavy_Path(*it,path);
}
else
{
++num_paths;
Parent[num_paths]=x;
Heavy_Path(*it,num_paths);
}
}
}
void Make_paths()
{
niv[1]=1;
Dfs(1);
memset(used,0,sizeof(used));
for(int i = 1; i<= n; i++ )
sort(g[i].begin(), g[i].end(), cmp);
Heavy_Path(1,1);
for(int i = 1; i<= num_paths; i++ )
{
if(i>1)
poz[i]=poz[i-1]+p[i-1].size()*4;
for(vector<int>::iterator it=p[i].begin(); it<p[i].end(); it++)
Update(1,1,(int)p[i].size(),niv[*it]-niv[Parent[where[*it]]],v[*it],poz[i]);
}
}
int main()
{
fin>>n>>m;
for(int i = 1; i<= n; i++)
fin >> v[i];
for(int i = 1; i< n; i++)
{
fin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
Make_paths();
for(int i = 1; i<= m; i++ )
{
fin >> op >> x >> y;
if(!op)
Update(1,1,(int)p[where[x]].size(),niv[x]-niv[Parent[where[x]]],y,poz[where[x]]);
else
{
sol=0;
while(where[x] != where[y])
{
if(niv[Parent[where[x]]]<niv[Parent[where[y]]])
swap(x,y);
sol = max(sol,query(1,1,(int)p[where[x]].size(),1,niv[x]-niv[Parent[where[x]]],poz[where[x]]));
x = Parent[where[x]];
}
if ( niv[x] > niv[y] )
swap(x,y);
sol = max(sol,query(1,1,(int)p[where[x]].size(),niv[x]-niv[Parent[where[x]]],niv[y]-niv[Parent[where[x]]],poz[where[x]]));
fout<<sol<<'\n';
}
}
fin.close();
fout.close();
return 0;
}