On this page
article
HLD - aresta
Sobre
SegTree de soma
query / update de soma das arestas
Complexidades:
build - O(n)
query_path - O(log^2 (n))
update_path - O(log^2 (n))
query_subtree - O(log(n))
update_subtree - O(log(n))
namespace seg { … }
Link original: hldAresta.cpp
Código
namespace hld {
vector<pair<int, int> > g[MAX];
int pos[MAX], sz[MAX];
int sobe[MAX], pai[MAX];
int h[MAX], v[MAX], t;
void build_hld(int k, int p = -1, int f = 1) {
v[pos[k] = t++] = sobe[k]; sz[k] = 1;
for (auto& i : g[k]) if (i.first != p) {
auto [u, w] = i;
sobe[u] = w; pai[u] = k;
h[u] = (i == g[k][0] ? h[k] : u);
build_hld(u, k, f); sz[k] += sz[u];
if (sz[u] > sz[g[k][0].first] or g[k][0].first == p)
swap(i, g[k][0]);
}
if (p*f == -1) build_hld(h[k] = k, -1, t = 0);
}
void build(int root = 0) {
t = 0;
build_hld(root);
seg::build(t, v);
}
ll query_path(int a, int b) {
if (a == b) return 0;
if (pos[a] < pos[b]) swap(a, b);
if (h[a] == h[b]) return seg::query(pos[b]+1, pos[a]);
return seg::query(pos[h[a]], pos[a]) + query_path(pai[h[a]], b);
}
void update_path(int a, int b, int x) {
if (a == b) return;
if (pos[a] < pos[b]) swap(a, b);
if (h[a] == h[b]) return (void)seg::update(pos[b]+1, pos[a], x);
seg::update(pos[h[a]], pos[a], x); update_path(pai[h[a]], b, x);
}
ll query_subtree(int a) {
if (sz[a] == 1) return 0;
return seg::query(pos[a]+1, pos[a]+sz[a]-1);
}
void update_subtree(int a, int x) {
if (sz[a] == 1) return;
seg::update(pos[a]+1, pos[a]+sz[a]-1, x);
}
int lca(int a, int b) {
if (pos[a] < pos[b]) swap(a, b);
return h[a] == h[b] ? b : lca(pai[h[a]], b);
}
}