Heavy-light-декомпозиция
Перейти к навигации
Перейти к поиску
#include <stdio.h> #include <vector> #include <queue> #include <set> #include <map> #include <algorithm> #include <iostream> using namespace std;
class ST {
int *t, size;
void build(int v, int vl, int vr) {
if (vl == vr) {
t[v] = 0;
return;
}
int vm = vl + (vr - vl) / 2;
build(2 * v + 1, vl, vm);
build(2 * v + 2, vm + 1, vr);
t[v] = max(t[2 * v + 1], t[2 * v + 2]);
}
int query(int v, int vl, int vr, int l, int r) {
if (r < vl || vr < l)
return -(1 << 30);
if (l <= vl && vr <= r)
return t[v];
int vm = vl + (vr - vl) / 2;
int ql = query(2 * v + 1, vl, vm, l, r);
int qr = query(2 * v + 2, vm + 1, vr, l, r);
return max(ql, qr);
}
void modify(int v, int vl, int vr, int pos, int val) {
if (pos < vl || vr < pos)
return;
if (pos == vl && vl == vr) {
t[v] += val;
return;
}
int vm = vl + (vr - vl) / 2;
modify(2 * v + 1, vl, vm, pos, val);
modify(2 * v + 2, vm + 1, vr, pos, val);
t[v] = max(t[2 * v + 1], t[2 * v + 2]);
}
public:
ST() {}
ST(int n) {
t = new int[4 * n];
size = n;
build(0, 0, size - 1);
}
int query(int l, int r) {
return query(0, 0, size - 1, l, r);
}
void modify(int pos, int val) {
modify(0, 0, size - 1, pos, val);
}
} st[100010];
int n, q, a, b;
char c;
vector<int> g[100010];
int tIn[100010], tOut[100010], timer, size[100010], parent[100010];
void dfs(int v) {
tIn[v] = ++timer;
size[v] = 1;
for (int i = 0; i < g[v].size(); i++) {
if (!tIn[g[v][i]]) {
parent[g[v][i]] = v;
dfs(g[v][i]);
size[v] += size[g[v][i]];
}
}
tOut[v] = ++timer;
}
bool isAncestor(int a, int v) {
return tIn[a] <= tIn[v] && tOut[v] <= tOut[a];
}
int chainInd[100010], chainPos[100010];
int chainSize[100010], chainRoot[100010];
int chainsCount;
void buildHLD(int v, int chain) {
chainInd[v] = chain;
chainPos[v] = chainSize[chain];
chainSize[chain]++;
if (chainSize[chain] == 1)
chainRoot[chain] = v;
int maxChild = -1;
for (int i = 0; i < g[v].size(); i++) {
if (g[v][i] != parent[v] && (maxChild == -1 || size[g[v][i]] > size[g[v][maxChild]]))
maxChild = i;
}
if (maxChild != -1)
for (int i = 0; i < g[v].size(); i++) {
if (g[v][i] == parent[v])
continue;
if (i == maxChild)
buildHLD(g[v][i], chain);
else
buildHLD(g[v][i], chainsCount++);
}
}
int queryHLD(int a, int b) {
int res = 0;
while (1) {
if (isAncestor(chainRoot[chainInd[a]], b))
break;
res = max(res, st[chainInd[a]].query(0, chainPos[a]));
a = parent[chainRoot[chainInd[a]]];
}
while (1) {
if (isAncestor(chainRoot[chainInd[b]], a))
break;
res = max(res, st[chainInd[b]].query(0, chainPos[b]));
b = parent[chainRoot[chainInd[b]]];
}
if (chainPos[a] > chainPos[b])
swap(a, b);
return max(res, st[chainInd[a]].query(chainPos[a], chainPos[b]));
}
int main() {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf("%d", &n);
for (int i = 0; i < n - 1; i++) {
scanf("%d%d", &a, &b);
g[a - 1].push_back(b - 1);
g[b - 1].push_back(a - 1);
}
dfs(0);
buildHLD(0, chainsCount++);
for (int i = 0; i < chainsCount; i++)
st[i] = ST(chainSize[i]);
scanf("%d", &q);
for (int i = 0; i < q; i++) {
scanf(" %c%d%d", &c, &a, &b);
if (c == 'I')
st[chainInd[a - 1]].modify(chainPos[a - 1], b);
else
printf("%d\n", queryHLD(a - 1, b - 1));
}
}
Ссылки на задачи
Ссылки
- e-maxx.ru — Heavy-light декомпозиция
- blog.anudeep2011.com — Heavy Light Decomposition
- CodeLibrary — Heavy-light tree decomposition for edges or vertices
- Algos — Heavy-light decomposition with segment trees in paths
- Algos — Finding LCA (Least common ancestor) of two vertices in the tree. Uses heavy-light decomposition