Pagini recente » Cod sursa (job #2840657) | Cod sursa (job #2235523) | Cod sursa (job #54477) | Cod sursa (job #574625) | Cod sursa (job #2733365)
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");
const int N = 1e5 + 5;
int a[4 * N];
int subarb[N], lant[N], poz[N], id[N], ad[N], val[N];
int tata[N][22];
int n;
int nr_noduri_viz, poz_aint, start = 1;
vector <int> v[N];
void dfs(int nod, int adancime) {
id[nod] = ++nr_noduri_viz;
subarb[nod] = 1;
ad[nod] = adancime;
for (auto it : v[nod]) {
if (!id[it]) {
dfs(it, adancime + 1);
subarb[nod] += subarb[it];
tata[it][0] = nod;
}
}
}
bool cmp_vecini(int x, int y) {
return subarb[x] > subarb[y];
}
void create_segments(int nod, int Lant) {
a[++poz_aint] = val[nod];
poz[nod] = poz_aint; //pozitia nodului nod in aint
lant[nod] = Lant;
sort (v[nod].begin(), v[nod].end(), cmp_vecini);
bool lant_curent = true;
for (auto it : v[nod]) {
if (!poz[it]) {
if (!lant_curent)
create_segments(it, it);
else {
create_segments(it, nod);
lant_curent = false;
}
}
}
}
namespace aint {
void build() {
for (int i = start - 1; i; --i) {
a[i] = max(a[i + i], a[i + i + 1]);
}
}
void Update(int nod) {
a[nod] = max(a[nod + nod], a[nod + nod + 1]);
if (nod > 1)
Update(nod / 2);
}
int Query(int st, int dr) {
int ans = 0;
if (st & 1)
ans = a[st++];
if (!(dr & 1))
ans = max(ans, a[dr--]);
if (st < dr)
ans = max(ans, Query(st / 2, dr / 2));
return ans;
}
}
namespace stramosi {
void rmq() {
for (int i = 1; i <= 20; ++i) {
for (int j = 1; j <= n; ++j) {
tata[j][i] = tata[tata[j][i - 1]][i - 1];
}
}
}
int find_daddy(int nod, int nivel) {
for (int i = 1, j = 0; i <= nivel; i <<= 1, ++j) {
if (i & nivel)
nod = tata[nod][j];
}
return nod;
}
int lca(int x, int y) {
if (ad[x] > ad[y])
x = find_daddy(x, ad[x] - ad[y]);
if (ad[y] > ad[x])
y = find_daddy(y, ad[y] - ad[x]);
if (x == y)
return x;
int ans = 1;
for (int i = 20; i >= 0; --i) {
if (tata[x][i] != tata[y][i]) {
x = tata[x][i];
y = tata[y][i];
} else ans = tata[x][i];
}
return ans;
}
}
int Query(int nod, int t) {
int ans = 0;
while(true) {
int l = lant[nod];
if (ad[l] <= ad[t]) {
l = t;
ans = max(aint::Query(poz[l], poz[nod]), ans);
break;
}
ans = max(aint::Query(poz[l], poz[nod]), ans);
nod = tata[l][0];
}
return ans;
}
int main() {
int m, x, y, type;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> val[i];
for (int i = 1; i < n; ++i) {
cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1, 1);
while (start < n)
start <<= 1;
poz_aint = start - 1;
create_segments(1, 1);
aint::build();
stramosi::rmq();
while (m--) {
cin >> type >> x >> y;
if (type == 0) {
a[poz[x]] = y;
aint::Update(poz[x] / 2);
} else {
int l = stramosi::lca(x, y);
// cout << Query(x, l) << ' ';
// cout << Query(y, l) << '\n';
cout << max(Query(x, l), Query(y, l)) << '\n';
}
}
return 0;
}