On this page
article
HLD - vertice
Sobre
SegTree de soma
query / update de soma dos vertices
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: hldVertice.cpp
Código
namespace hld {
vector<int> g[MAX];
int pos[MAX], sz[MAX];
int peso[MAX], pai[MAX];
int h[MAX], v[MAX], t;
void build_hld(int k, int p = -1, int f = 1) {
v[pos[k] = t++] = peso[k]; sz[k] = 1;
for (auto& i : g[k]) if (i != p) {
pai[i] = k;
h[i] = (i == g[k][0] ? h[k] : i);
build_hld(i, k, f); sz[k] += sz[i];
if (sz[i] > sz[g[k][0]] or g[k][0] == 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 (pos[a] < pos[b]) swap(a, b);
if (h[a] == h[b]) return seg::query(pos[b], 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 (pos[a] < pos[b]) swap(a, b);
if (h[a] == h[b]) return (void)seg::update(pos[b], pos[a], x);
seg::update(pos[h[a]], pos[a], x); update_path(pai[h[a]], b, x);
}
ll query_subtree(int a) {
return seg::query(pos[a], pos[a]+sz[a]-1);
}
void update_subtree(int a, int x) {
seg::update(pos[a], 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);
}
}