#include <fstream>
#include <vector>
#include <algorithm>
#define MAX 100005
#define pb push_back
#define leftSon (nod << 1)
#define rightSon ((nod << 1) + 1)
using namespace std;
vector<int> v[MAX], C[MAX];
int lvl[MAX], weight[MAX], l[MAX], lDad[MAX], lLvl[MAX], aInt[MAX << 2], val[MAX], lPoz[MAX];
int cnt, n, m, a, b, tip;
void dfs(int nod, int dad, int nivel)
{
lvl[nod] = nivel;
weight[nod] = 1;
bool leaf = true; int heaviest = -1;
for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); it++)
{
if((*it) == dad) continue;
leaf = false;
dfs((*it), nod, nivel + 1);
weight[nod] += weight[(*it)];
if(!heaviest || weight[heaviest] < weight[(*it)]) heaviest = (*it);
}
if(leaf)
{
l[nod] = ++cnt;
C[cnt].pb(nod);
return;
}
l[nod] = l[heaviest];
C[l[nod]].pb(nod);
for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); it++)
{
if((*it) == heaviest || (*it) == dad) continue;
lDad[l[(*it)]] = nod;
lLvl[l[(*it)]] = lvl[nod];
}
}
void build(int nod, int left, int right, int decalaj, int lant)
{
if(left == right)
{
aInt[nod + decalaj] = val[ C[lant][left - 1] ];
return;
}
int m = (left + right) >> 1;
build(leftSon, left, m, decalaj, lant);
build(rightSon, m + 1, right, decalaj, lant);
aInt[nod + decalaj] = max(aInt[leftSon + decalaj], aInt[rightSon + decalaj]);
}
void makePaths()
{
dfs(1, 0, 1);
for(int i = 1; i <= cnt; i++)
{
reverse(C[i].begin(), C[i].end());
lPoz[i] = lPoz[i - 1] + C[i - 1].size() * 4;
build(1, 1, C[i].size(), lPoz[i], i);
}
}
void update(int nod, int left, int right, int poz, int val, int decalaj)
{
if(left == right)
{
aInt[nod + decalaj] = val;
return;
}
int m = (left + right) >> 1;
if(poz <= m) update(leftSon, left, m, poz, val, decalaj);
else update(rightSon, m + 1, right, poz, val, decalaj);
aInt[nod + decalaj] = max(aInt[leftSon + decalaj], aInt[rightSon + decalaj]);
}
int query(int nod, int left, int right, int l, int r, int decalaj)
{
if(l <= left && right <= r)
return aInt[nod + decalaj];
int m = (left + right) >> 1, sol = 0;
if(l <= m) sol = max(sol, query(leftSon, left, m, l, r, decalaj));
if(m < r) sol = max(sol, query(rightSon, m + 1, right, l, r, decalaj));
return sol;
}
int main()
{
ifstream in("heavypath.in");
in>>n>>m;
for(int i = 1; i <= n; i++) in>>val[i];
for(int i = 1; i < n; i++)
{
in>>a>>b;
v[a].pb(b);
v[b].pb(a);
}
makePaths(); ofstream out("heavypath.out");
for(int i = 1; i <= m; i++)
{
in>>tip>>a>>b;
if(!tip) update(1, 1, C[l[a]].size(), lvl[a] - lLvl[l[a]], b, lPoz[l[a]]);
else
{
int sol = 0;
while(1)
{
if(l[a] == l[b])
{
if(lvl[a] > lvl[b]) swap(a, b);
sol = max(sol, query(1, 1, C[l[a]].size(), lvl[a] - lLvl[l[a]], lvl[b] - lLvl[l[b]], lPoz[l[a]]));
break;
}
if(lLvl[l[a]] < lLvl[l[b]]) swap(a, b);
sol = max(sol, query(1, 1, C[l[a]].size(), 1, lvl[a] - lLvl[l[a]], lPoz[l[a]]));
a = lDad[l[a]];
}
out<<sol<<"\n";
}
}
out.close();
return 0;
}