pub mod tree {
use crate::{
bit_length_with_count_leading_zeros_u64::bit_length,
tree_bfs_depth_with_abstract::tree_depths,
tree_bfs_parent_with_abstract::tree_parents,
};
pub struct Doubling {
a: Vec<Vec<usize>>, d: Vec<usize>, }
impl Doubling {
pub fn new(e: &[(usize, usize)]) -> Self {
const R: usize = 0;
let n = e.len() + 1;
let d = tree_depths(&e, R);
let k = bit_length(*d.iter().max().unwrap() as u64).max(1) as usize;
let mut a = vec![vec![n; n]; k];
let mut p = tree_parents(&e, R);
p[R] = Some(R);
a[0] = p.iter().map(|&v| v.unwrap()).collect();
for i in 0..k - 1 {
for j in 0..n {
a[i + 1][j] = a[i][a[i][j]];
}
}
Self { a, d }
}
pub fn get(
&self,
mut u: usize,
mut v: usize,
) -> usize {
if self.d[u] > self.d[v] {
std::mem::swap(&mut u, &mut v);
}
let d = self.d[v] - self.d[u];
for i in 0..bit_length(d as u64) as usize {
if d >> i & 1 == 1 {
v = self.a[i][v];
}
}
if v == u {
return u;
}
for a in self.a.iter().rev() {
let (nu, nv) = (a[u], a[v]);
if nu != nv {
u = nu;
v = nv;
}
}
self.a[0][u]
}
}
use crate::{
tree_edges_to_graph::tree_edges_to_graph,
union_find_low_memory_with_trait::*,
union_find_traits::*,
};
pub fn tarjan(
e: &[(usize, usize)],
qs: &[(usize, usize)],
) -> Vec<usize> {
fn dfs(
g: &Vec<Vec<usize>>,
q: &Vec<Vec<(usize, usize)>>,
visited: &mut Vec<bool>,
uf: &mut UnionFind,
a: &mut Vec<usize>,
lca: &mut Vec<usize>,
u: usize,
) {
visited[u] = true;
a[u] = u;
for &v in g[u].iter() {
if visited[v] {
continue;
}
dfs(g, q, visited, uf, a, lca, v);
uf.unite(u, v);
a[uf.root(u)] = u;
}
q[u].iter().filter(|&&(v, _)| visited[v]).for_each(|&(v, i)| {
lca[i] = a[uf.root(v)];
});
}
let n = e.len() + 1;
let graph = tree_edges_to_graph(e);
let mut q = vec![vec![]; n];
for (i, &(u, v)) in qs.iter().enumerate() {
q[u].push((v, i));
q[v].push((u, i));
}
let mut visited = vec![false; n];
let mut uf = UnionFind::new(n);
let mut ancestor = vec![n; n];
let mut lca = vec![n; qs.len()];
dfs(&graph, &q, &mut visited, &mut uf, &mut ancestor, &mut lca, 0);
lca
}
use crate::heavly_light_decomposition::heavy_light_decompose;
pub struct LCAHLD {
p: Vec<Option<usize>>, d: Vec<usize>, r: Vec<usize>, }
impl LCAHLD {
pub fn new(
tree_edges: &[(usize, usize)],
root: usize,
) -> Self {
Self {
p: tree_parents(tree_edges, root),
d: tree_depths(tree_edges, root),
r: heavy_light_decompose(tree_edges, root),
}
}
pub fn get(
&self,
mut u: usize,
mut v: usize,
) -> usize {
use std::mem::swap;
while self.r[u] != self.r[v] {
if self.d[self.r[u]] > self.d[self.r[v]] {
swap(&mut u, &mut v);
}
v = self.p[self.r[v]].unwrap();
}
if self.d[u] <= self.d[v] {
u
} else {
v
}
}
}
use crate::{
ett::{
first_positions,
tour_nodes,
},
query::RangeMinimumQuery,
};
pub struct EulerTourRMQ<Q> {
first_pos: Vec<usize>,
rmq: Q,
}
impl<Q> EulerTourRMQ<Q> {
pub fn new(
tree_edges: &[(usize, usize)],
root: usize,
) -> Self
where
Q: std::iter::FromIterator<(usize, usize)>,
{
let tour_nodes = tour_nodes(tree_edges, root);
let depth = tree_depths(tree_edges, root);
let first_pos = first_positions(&tour_nodes);
let depth =
tour_nodes.iter().map(|&u| depth[u]).collect::<Vec<_>>();
let rmq =
Q::from_iter(depth.into_iter().zip(tour_nodes.into_iter()));
Self { first_pos, rmq }
}
pub fn get(
&mut self,
u: usize,
v: usize,
) -> usize
where
Q: RangeMinimumQuery<T = (usize, usize)>,
{
let mut left = self.first_pos[u];
let mut right = self.first_pos[v];
if left > right {
std::mem::swap(&mut left, &mut right);
}
self.rmq.range_minimum(left, right + 1).1
}
}
use crate::{
algebraic_structure_impl::*,
group_theory_id::Min,
segment_tree_with_static_monoid::Segtree,
};
type CommonG = GroupApprox<(usize, usize), Min>;
#[allow(dead_code)]
type ETRMQSeg = EulerTourRMQ<Segtree<CommonG>>;
use crate::sparse_table_with_static_idempotent_semigroup::SparseTable;
#[allow(dead_code)]
type ETRMQSpT = EulerTourRMQ<SparseTable<CommonG>>;
use crate::sqrt_decomposition::SqrtDecomposition;
#[allow(dead_code)]
type ETRMQSqD = EulerTourRMQ<SqrtDecomposition<CommonG>>;
use crate::sparse_table_with_static_idempotent_semigroup::*;
#[allow(dead_code)]
type ETRMQDSpT = EulerTourRMQ<DisjointSparseTable<CommonG>>;
}
pub mod dyn_tree {
}
pub mod dag {
}