Skip to content
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
6ff9e79
saving progress
lrvideckis Jul 1, 2024
fef6a44
saving progress
lrvideckis Jul 1, 2024
c40002e
Update mono_st.rs
lrvideckis Jul 1, 2024
7a899cc
saving progress
lrvideckis Jul 1, 2024
fd59fe1
saving progress
lrvideckis Jul 1, 2024
90572e9
saving progress
lrvideckis Jul 1, 2024
96635dd
another assert
lrvideckis Jul 1, 2024
882bdba
remove
lrvideckis Jul 1, 2024
03682e8
add test
lrvideckis Jul 1, 2024
2eb1c12
asdf
lrvideckis Jul 1, 2024
72658ee
finish
lrvideckis Jul 1, 2024
8eb0abe
better
lrvideckis Jul 1, 2024
c656614
fix
lrvideckis Jul 1, 2024
153cec0
uncomment
lrvideckis Jul 1, 2024
dc0c736
Update mono_st.rs
lrvideckis Jul 3, 2024
c87a544
Update mono_range.rs
lrvideckis Jul 3, 2024
574b24f
Update mono_st.rs
lrvideckis Jul 3, 2024
e1f81e5
fix
lrvideckis Jul 3, 2024
8b1614a
change style
lrvideckis Jul 3, 2024
35a88ad
nit
lrvideckis Jul 3, 2024
7646a4a
change
lrvideckis Jul 3, 2024
2dc1895
nits
lrvideckis Jul 3, 2024
0f85db9
different style
lrvideckis Jul 3, 2024
460f332
golf
lrvideckis Jul 3, 2024
fc29bdf
consistency with c++ PTC
lrvideckis Jul 3, 2024
55b71bd
finish doc for mono st
lrvideckis Jul 3, 2024
fd3b167
simplify test
lrvideckis Jul 3, 2024
00acb23
add
lrvideckis Jul 3, 2024
cbb0b82
add docs for mono range
lrvideckis Jul 3, 2024
5f49d8c
fix typo
lrvideckis Jul 3, 2024
016e02e
nit
lrvideckis Jul 3, 2024
c97712a
fix
lrvideckis Jul 3, 2024
54936fb
nit to docs
lrvideckis Jul 4, 2024
62e4fc6
now ACs
lrvideckis Jul 4, 2024
2b56c9d
virt tree
lrvideckis Jul 6, 2024
438c6f7
finish docs
lrvideckis Jul 6, 2024
3a1fb27
finished test
lrvideckis Jul 6, 2024
ff31ec1
make dist const
lrvideckis Jul 6, 2024
38343f0
consistent var names
lrvideckis Jul 7, 2024
3f89810
Merge branch 'main' into compress_tree
lrvideckis Jul 8, 2024
69c561c
Merge branch 'main' into compress_tree
lrvideckis Jul 17, 2024
b9afd08
Merge branch 'main' into compress_tree
cameroncuster Jul 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,11 @@ path = "examples/helpers/lis_yosupo.rs"
[[example]]
name = "lis_pop"
path = "examples/helpers/lis_pop.rs"

[[example]]
name = "mono_st"
path = "examples/monotonic/mono_st.rs"

[[example]]
name = "hld_aux_tree"
path = "examples/graphs/hld_aux_tree.rs"
79 changes: 79 additions & 0 deletions examples/graphs/hld_aux_tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/GRL_5_B

use proconio::input;
use programming_team_code_rust::graphs::hld::HLD;
use std::collections::VecDeque;

fn main() {
input! {
n: usize,
edges: [(usize, usize, u32); n - 1],
}

let mut adj_weighted = vec![vec![]; n];
let mut adj = vec![vec![]; n];
for &(u, v, w) in &edges {
adj[u].push(v);
adj[v].push(u);
adj_weighted[u].push((v, w));
adj_weighted[v].push((u, w));
}
let adj_weighted = adj_weighted;

let mut dist = vec![0; n];
{
fn dfs(u: usize, p: Option<usize>, adj_weighted: &[Vec<(usize, u32)>], dist: &mut [u32]) {
for &(v, w) in &adj_weighted[u] {
if Some(v) == p {
continue;
}
dist[v] = w + dist[u];
dfs(v, Some(u), adj_weighted, dist);
}
}
dfs(0, None, &adj_weighted, &mut dist);
}

let hld = HLD::new(&mut adj, true);

let weighted_dist = |u: usize, v: usize| -> u32 {
let lc = hld.lca(u, v);
dist[u] + dist[v] - 2 * dist[lc]
};

let mut diam_u = 0;
for i in 1..n {
if weighted_dist(0, i) > weighted_dist(0, diam_u) {
diam_u = i;
}
}
let mut diam_v = 0;
for i in 1..n {
if weighted_dist(diam_u, i) > weighted_dist(diam_u, diam_v) {
diam_v = i;
}
}

for u in 0..n {
let (par, to_node) = hld.aux_tree(vec![diam_u, diam_v, u]);
let mut aux_adj = vec![vec![]; par.len()];
for i in 1..par.len() {
let edge_w = dist[to_node[i]] - dist[to_node[par[i]]];
aux_adj[i].push((par[i], edge_w));
aux_adj[par[i]].push((i, edge_w));
}
let mut q = VecDeque::new();
q.push_back((to_node.iter().position(|&x| x == u).unwrap(), None, 0));
let mut res = 0;
while let Some((node, parent, curr_dist)) = q.pop_front() {
res = res.max(curr_dist);
for &(v, w) in &aux_adj[node] {
if Some(v) == parent {
continue;
}
q.push_back((v, Some(node), curr_dist + w));
}
}
println!("{}", res);
}
}
87 changes: 87 additions & 0 deletions examples/monotonic/mono_st.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/staticrmq

use proconio::input;
use programming_team_code_rust::data_structures::rmq::RMQ;
use programming_team_code_rust::monotonic::mono_range::mono_range;
use programming_team_code_rust::monotonic::mono_st::mono_st;

fn main() {
input! {
n: usize,
q: usize,
a: [u32; n],
}

let rmq = RMQ::new(
&(0..n).map(|i| (i, i)).collect::<Vec<_>>(),
|(min_i1, max_i1), (min_i2, max_i2)| {
let min_idx = if a[min_i1] < a[min_i2] {
min_i1
} else {
min_i2
};
let max_idx = if a[max_i1] > a[max_i2] {
max_i1
} else {
max_i2
};
(min_idx, max_idx)
},
);

let compares = vec![
|x: u32, y: u32| -> bool { x.le(&y) },
|x: u32, y: u32| -> bool { x.lt(&y) },
|x: u32, y: u32| -> bool { x.ge(&y) },
|x: u32, y: u32| -> bool { x.gt(&y) },
];

let mut le = Vec::new();
let mut ri = Vec::new();
for &cmp in &compares {
le.push(mono_st(&a, |&x, &y| cmp(x, y)));
ri.push(mono_range(le.last().unwrap()));
}
let le = le;
let ri = ri;

for curr_le in &le {
let mut count_index = vec![0; n];
for i in 0..n {
let mut j = i.wrapping_sub(1);
while j != curr_le[i] {
count_index[j] += 1;
j = curr_le[j];
}
}
let mut j = n.wrapping_sub(1);
while j != usize::MAX {
count_index[j] += 1;
j = curr_le[j];
}
assert_eq!(count_index, vec![1; n]);
}

for _ in 0..q {
input! {
l: usize,
r: usize,
}

let (min_idx, max_idx) = rmq.query(l..r);

for i in 0..4 {
let idx = if i < 2 { min_idx } else { max_idx };
let rmq_res = rmq.query(le[i][idx].wrapping_add(1)..ri[i][idx]);
assert_eq!(a[if i < 2 { rmq_res.0 } else { rmq_res.1 }], a[idx]);
if le[i][idx] != usize::MAX {
assert!(compares[i](a[le[i][idx]], a[idx]));
}
if ri[i][idx] < n {
assert!(!compares[i](a[idx], a[ri[i][idx]]));
}
}

println!("{}", a[min_idx]);
}
}
39 changes: 39 additions & 0 deletions src/graphs/hld.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! # Heavy Light Decomposition

use crate::graphs::dfs_order::{get_dfs_postorder, get_dfs_preorder};
use crate::monotonic::mono_st::mono_st;
use std::ops::Range;

/// # Example
Expand Down Expand Up @@ -200,4 +201,42 @@ impl HLD {
None
}
}

/// # Auxiliary Tree
///
/// - see <https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/CompressTree.h>
///
/// # Example
/// ```
/// use programming_team_code_rust::graphs::hld::HLD;
///
/// let n = 5;
/// let mut adj = vec![vec![]; n];
/// for (u, v) in [(0,1), (1,2), (2,3), (2,4)] {
/// adj[u].push(v);
/// adj[v].push(u);
/// }
///
/// let hld = HLD::new(&mut adj, false);
///
/// let (par, to_node) = hld.aux_tree(vec![0, 3, 4]);
/// // 0, 1, .., par.len()-1 is a topological/dfs order of aux tree
/// assert_eq!(par, [usize::MAX, 0, 1, 1]);
/// assert_eq!(to_node, [0, 2, 3, 4]);
/// ```
///
/// # Complexity
/// - k = nodes.len()
/// - Time: O((k log k) + (k log n))
/// - Space: O(k)
pub fn aux_tree(&self, mut nodes: Vec<usize>) -> (Vec<usize>, Vec<usize>) {
nodes.sort_by(|&a, &b| self.tin[a].cmp(&self.tin[b]));
let siz = nodes.len();
for i in 1..siz {
nodes.push(self.lca(nodes[i - 1], nodes[i]));
}
nodes.sort_by(|&a, &b| self.tin[a].cmp(&self.tin[b]));
nodes.dedup();
(mono_st(&nodes, |&x, &y| self.in_sub(x, y)), nodes)
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
pub mod data_structures;
pub mod graphs;
pub mod helpers;
pub mod monotonic;
pub mod numbers;
pub mod strings;
3 changes: 3 additions & 0 deletions src/monotonic/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! # Monotonic
pub mod mono_range;
pub mod mono_st;
30 changes: 30 additions & 0 deletions src/monotonic/mono_range.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! # Monotonic Range

/// Gets vec ri where ri\[i\] = smallest index such that i < ri\[i\] && !a\[i\].cmp(&a\[ri\[i\]\]), or n
///
/// # Example
/// ```
/// use programming_team_code_rust::monotonic::mono_st::mono_st;
/// use programming_team_code_rust::monotonic::mono_range::mono_range;
///
/// let a: Vec<u32> = vec![3, 1, 2, 2];
///
/// let le = mono_st(&a, |x, y| x.lt(y));
/// let ri = mono_range(&le);
/// assert_eq!(ri, [1, 4, 3, 4]);
/// ```
///
/// # Complexity
/// - Time: O(n)
/// - Space: O(n)
pub fn mono_range(le: &[usize]) -> Vec<usize> {
let mut ri = vec![le.len(); le.len()];
for i in 0..le.len() {
let mut j = i.wrapping_sub(1);
while j != le[i] {
ri[j] = i;
j = le[j];
}
}
ri
}
51 changes: 51 additions & 0 deletions src/monotonic/mono_st.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! # Monotonic Stack

/// Gets vec le where le\[i\] = largest index such that le\[i\] < i && a\[le\[i\]\].cmp(&a\[i\]), or usize::MAX
///
/// # Example
/// ```
/// use programming_team_code_rust::monotonic::mono_st::mono_st;
///
/// let a: Vec<u32> = vec![3, 1, 2, 2];
/// let n = a.len();
///
/// assert_eq!(mono_st(&a, |x, y| x.lt(y)), [usize::MAX, usize::MAX, 1, 1]);
/// assert_eq!(mono_st(&a, |x, y| x.le(y)), [usize::MAX, usize::MAX, 1, 2]);
/// assert_eq!(mono_st(&a, |x, y| x.gt(y)), [usize::MAX, 0, 0, 0]);
/// assert_eq!(mono_st(&a, |x, y| x.ge(y)), [usize::MAX, 0, 0, 2]);
///
/// // simulate popping off stack for single index
/// let le = mono_st(&a, |x, y| x.lt(y));
/// let mut seen_index = vec![0; n];
/// for i in 0..n {
/// let mut j = i.wrapping_sub(1);
/// while j != le[i] {
/// let range = le[j].wrapping_add(1)..j; // for all indexes k in range: !cmp(&a[k], &a[j])
/// seen_index[j] += 1;
/// j = le[j];
/// }
/// }
///
/// // clear the stack at the end
/// let mut j = n.wrapping_sub(1);
/// while j != usize::MAX {
/// seen_index[j] += 1;
/// j = le[j];
/// }
///
/// assert_eq!(seen_index, vec![1; n]);
/// ```
///
/// # Complexity
/// - Time: O(n)
/// - Space: O(n)
pub fn mono_st<T: Ord, F: Fn(&T, &T) -> bool>(a: &[T], cmp: F) -> Vec<usize> {
let mut le = vec![0; a.len()];
for i in 0..a.len() {
le[i] = i.wrapping_sub(1);
while le[i] != usize::MAX && !cmp(&a[le[i]], &a[i]) {
le[i] = le[le[i]];
}
}
le
}