struct HLD {
int n;
vector<int> sz, top, dep, fa, in, out, seq;
vector<vector<int>> ver;
int cur;
HLD() {}
HLD(int n) {
init(n);
}
void init(int n) {
this->n = n;
sz.resize(n);
top.resize(n);
dep.resize(n);
fa.resize(n);
in.resize(n);
out.resize(n);
seq.resize(n);
cur = 0;
ver.assign(n, {});
}
void addEdge(int u, int v) {
ver[u].push_back(v);
ver[v].push_back(u);
}
void work(int root = 0) {
top[root] = root;
dep[root] = 0;
fa[root] = -1;
dfs1(root);
dfs2(root);
}
void dfs1(int u) {
if(fa[u] != -1) {
ver[u].erase(find(ver[u].begin(), ver[u].end(), fa[u])); //把存的边中父节点删掉
}
sz[u] = 1;
for(auto &v : ver[u]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
sz[u] += sz[v];
if(sz[v] > sz[ver[u][0]]) { //ver[u][0]存的是u的重儿子
swap(v, ver[u][0]);
}
}
}
void dfs2(int u) {
in[u] = cur ++ ;
seq[in[u]] = u;
for(auto v : ver[u]) {
top[v] = v == ver[u][0] ? top[u] : v; //重儿子的重链顶点就是他自己的重链顶点,轻儿子的重链顶点就是轻儿子自己
dfs2(v);
}
out[u] = cur;
}
int lca(int u, int v) {
while(top[u] != top[v]) {
if(dep[top[u]] > dep[top[v]]) {
u = fa[top[u]];
} else {
v = fa[top[v]];
}
}
return dep[u] < dep[v] ? u : v; //此时u和v在一条重链上,所以原始的u和v的lca就是现在u和v中深度较小的那个
}
int dist(int u, int v) {
return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}
int jump(int u, int k) {
if(dep[u] < k) {
return -1;
}
int d = dep[u] - k;
while(dep[top[u]] > d) {
u = fa[top[u]];
}
return seq[in[u] - dep[u] + d];
}
bool isAncester(int u, int v) {
return in[u] <= in[v] && in[v] < out[u];
}
int rootedFa(int u, int v) {
swap(u, v);
if(u == v) {
return u;
}
if(!isAncester(u, v)) {
return fa[u];
}
auto it = upper_bound(ver[u].begin(), ver[u].end(), v, [&](int x, int y) {
return in[x] < in[y];
}) - 1;
return *it;
}
int rootedSize(int u, int v) {
if(u == v) {
return n;
}
if(!isAncester(v, u)) {
return sz[v];
}
return n - sz[rootedFa(u, v)];
}
int rootedLca(int a, int b, int c) {
return lca(a, b) ^ lca(b, c) ^ lca(c, a);
}
};