#include <bits/stdc++.h>
using namespace std;
///plant- poz in lant, label - lant, asc - lantascendent, qlant - query lant, pos - positia in aint, asc - elementul care este ianintea primului element din lant in arbore, flbl - primul element din lant
int n, greu[100001], w[100001], f[100001], label[100001], plant[100001], asc[100001], pos[100001], flbl[100001], lvl[100001], freelabel = 2, poz;
vector<int> ad[100001];
bool cmp(int a, int b)
{
return w[a] > w[b];
}
void dfsweight(int nod)
{
int ok = 0;
f[nod] = 1;
for (auto i : ad[nod])
if (f[i] == 0)
{
lvl[i] = lvl[nod] + 1;
dfsweight(i);
f[i] = 0;
}
for (auto i : ad[nod])
if (f[i] == 0)
w[nod] += w[i];
}
void dfslabel(int nod)
{
f[nod] = 1;
pos[nod] = ++poz;
int x = 0;
while (x < ad[nod].size() && f[ad[nod][x]] == 1)
x++;
if (x < ad[nod].size())
{
label[ad[nod][x]] = label[nod];
plant[ad[nod][x]] = plant[nod] + 1;
for (auto i : ad[nod])
if (label[i] == 0)
label[i] = freelabel, plant[i] = 1, asc[freelabel] = nod, flbl[freelabel] = i, freelabel++;
for (auto i : ad[nod])
if (f[i] == 0)
dfslabel(i);
}
}
struct AINT
{
int aint[400001];
void update(int ind, int pos, int val, int st, int dr)
{
if (st == dr)
aint[ind] = val;
else
{
if (pos <= (st + dr) / 2)
update(2 * ind, pos, val, st, (st + dr) / 2);
else
update(2 * ind + 1, pos, val, (st + dr) / 2 + 1, dr);
aint[ind] = max(aint[2 * ind], aint[2 * ind + 1]);
}
}
int query(int ind, int stq, int drq, int st, int dr)
{
if (st >= stq && dr <= drq)
return aint[ind];
else
{
int maxx = 0;
if (stq <= (st + dr) / 2)
maxx = max(maxx, query(2 * ind, stq, drq, st, (st + dr) / 2));
if (drq > (st + dr) / 2)
maxx = max(maxx, query(2 * ind + 1, stq, drq, (st + dr) / 2 + 1, dr));
return maxx;
}
}
};
AINT v;
int query(int x, int y)
{
int maxx = 0, lbl, jos, sus;
while (x > 0 && y > 0 && label[x] != label[y])
{
if (lvl[x] < lvl[y])
swap(x, y);
if (label[asc[label[y]]] == label[x])
swap(x, y);
jos = pos[flbl[label[x]]], sus = pos[x];
maxx = max(maxx, v.query(1, jos, sus, 1, n));
x = asc[label[x]];
}
if (lvl[x] < lvl[y])
swap(x, y);
jos = pos[y], sus = pos[x];
maxx = max(maxx, v.query(1, jos, sus, 1, n));
return maxx;
}
int main()
{
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
int m, a, b, i, c;
for (i = 0; i <= 4 * n; i++)
v.aint[i] = 0;
cin >> n >> m;
for (i = 1; i <= n; i++)
w[i] = 1, cin >> greu[i];
for (i = 0; i < n - 1; i++)
{
cin >> a >> b;
ad[a].push_back(b);
ad[b].push_back(a);
}
lvl[1] = 1;
dfsweight(1);
for (i = 1; i <= n; i++)
w[i]--, f[i] = 0, sort(ad[i].begin(), ad[i].end(), cmp);
label[1] = 1, plant[1] = 1, flbl[1] = 1, flbl[1] = 1, asc[1] = 1;
dfslabel(1);
for (i = 1; i <= n; i++)
v.update(1, pos[i], greu[i], 1, n);
while (m)
{
cin >> c >> a >> b;
if (c == 0)
v.update(1, pos[a], b, 1, n);
else
cout << query(a, b) << '\n';
m--;
}
return 0;
}