This documentation is automatically generated by competitive-verifier/competitive-verifier
#pragma once
#include "algo/common.h"
#include "algo/ds/sparse_table.h"
#include "algo/utils/bits.h"
namespace algo::graph {
struct lca {
// Note that adj must be a tree. Don't forget to set root!
lca(const std::vector<std::vector<int>> &adj, int root = 0)
: n(sz(adj)), height(n), first(n), st(2 * n, [&](int a, int b) {
return height[a] < height[b] ? a : b;
}) {
euler.reserve(2 * n);
dfs(root, root, 0, adj);
st.init(euler);
}
// Lowest common ancestor of u, v
int par(int u, int v) {
int l = first[u], r = first[v];
if (l > r) std::swap(l, r);
return st.query(l, r);
}
private:
int n;
std::vector<int> height, euler, first;
ds::sparse_table<int> st;
void dfs(int v, int p, int h, const std::vector<std::vector<int>> &adj) {
height[v] = h;
first[v] = sz(euler);
euler.push_back(v);
for (int u : adj[v]) {
if (u != p) {
dfs(u, v, h + 1, adj);
euler.push_back(v);
}
}
}
};
}; // namespace algo::graph
#line 2 "algo/common.h"
#ifndef PREPROCESS
#include <bits/stdc++.h>
#endif
namespace algo {}
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#line 3 "algo/ds/common.h"
namespace algo::ds {
template <typename T>
T min(const T &a, const T &b) {
return std::min(a, b);
}
}; // namespace algo::ds
#line 3 "algo/utils/bits.h"
namespace algo::utils {
// Returns number of set bits in x
constexpr int popcnt(int64_t x) {
return __builtin_popcountll(x);
}
// Returns floor(log_2(x))
constexpr int lg2(uint64_t x) {
return std::bit_width(x) - 1;
}
} // namespace algo::utils
#line 5 "algo/ds/sparse_table.h"
namespace algo::ds {
template <typename T>
struct sparse_table {
// Must be constructed with idempotent function. Call init() after if using
// this constructor.
sparse_table(int _n, const std::function<T(T, T)> &op = min<T>)
: n(_n), k(utils::lg2(n)), op(op), st(k + 1, std::vector<T>(n)) {
}
// Must be constructed with idempotent function
sparse_table(const std::vector<T> &a,
const std::function<T(T, T)> &op = min<T>)
: sparse_table(sz(a), op) {
init(a);
}
void init(const std::vector<T> &a) {
assert(sz(a) <= n);
std::copy(all(a), st[0].begin());
for (int i = 1; i <= k; i++) {
for (int j = 0; j + (1 << i) <= n; j++) {
st[i][j] = op(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
}
}
}
// Queries on [l, r]
T query(int l, int r) {
int i = utils::lg2(r - l + 1);
return op(st[i][l], st[i][r - (1 << i) + 1]);
}
friend std::ostream &operator<<(std::ostream &os, const sparse_table &t) {
return os << t.st[0];
}
private:
int n, k;
std::function<T(T, T)> op;
std::vector<std::vector<T>> st;
};
} // namespace algo::ds
#line 5 "algo/graph/lca.h"
namespace algo::graph {
struct lca {
// Note that adj must be a tree. Don't forget to set root!
lca(const std::vector<std::vector<int>> &adj, int root = 0)
: n(sz(adj)), height(n), first(n), st(2 * n, [&](int a, int b) {
return height[a] < height[b] ? a : b;
}) {
euler.reserve(2 * n);
dfs(root, root, 0, adj);
st.init(euler);
}
// Lowest common ancestor of u, v
int par(int u, int v) {
int l = first[u], r = first[v];
if (l > r) std::swap(l, r);
return st.query(l, r);
}
private:
int n;
std::vector<int> height, euler, first;
ds::sparse_table<int> st;
void dfs(int v, int p, int h, const std::vector<std::vector<int>> &adj) {
height[v] = h;
first[v] = sz(euler);
euler.push_back(v);
for (int u : adj[v]) {
if (u != p) {
dfs(u, v, h + 1, adj);
euler.push_back(v);
}
}
}
};
}; // namespace algo::graph