From 4f6b2a9a5f021a3a3ff64f52507df9a9cd66517f Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Sat, 13 Jul 2024 10:56:29 -0500 Subject: [PATCH 1/7] nits --- src/graphs/hld.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/graphs/hld.rs b/src/graphs/hld.rs index 076a60d8..8a0695bf 100644 --- a/src/graphs/hld.rs +++ b/src/graphs/hld.rs @@ -33,6 +33,7 @@ pub struct HLD { pub p: Vec>, /// time in pub tin: Vec, + d: Vec, ord: Vec, siz: Vec, head: Vec, @@ -66,16 +67,19 @@ impl HLD { } let mut tin = vec![0; n]; let mut head = vec![0; n]; + let mut d = vec![0; n]; let ord = get_dfs_preorder(adj); for (i, &u) in ord.iter().enumerate() { tin[u] = i; for &v in &adj[u] { + d[v] = 1 + d[u]; head[v] = if v == adj[u][0] { head[u] } else { v }; } } HLD { p, siz, + d, ord, tin, head, @@ -92,7 +96,7 @@ impl HLD { let mut u_anc = false; loop { if self.tin[u] > self.tin[v] { - std::mem::swap(&mut u, &mut v); + (u, v) = (v, u); u_anc = !u_anc; } if self.head[u] == self.head[v] { @@ -124,7 +128,7 @@ impl HLD { pub fn lca(&self, mut u: usize, mut v: usize) -> usize { loop { if self.tin[u] > self.tin[v] { - std::mem::swap(&mut u, &mut v); + (u, v) = (v, u); } if self.head[u] == self.head[v] { return u; @@ -133,16 +137,13 @@ impl HLD { } } - /// If !vals_edges, then gets number of nodes on path from u to v - /// If vals_edges, then gets number of edges on path from u to v + /// Gets number of edges on path from u to v /// /// # Complexity /// - Time: O(log n) /// - Space: O(1) pub fn dist(&self, u: usize, v: usize) -> usize { - let mut dst = 0; - self.path(u, v, |range, _| dst += range.len()); - dst + self.d[u] + self.d[v] - 2 * self.d[self.lca(u, v)] } /// Returns true iff v is in u's subtree @@ -151,7 +152,7 @@ impl HLD { /// - Time: O(1) /// - Space: O(1) pub fn in_sub(&self, u: usize, v: usize) -> bool { - u == v || self.sub_tree(u).contains(&self.tin[v]) + (self.tin[u]..self.tin[u] + self.siz[u]).contains(&self.tin[v]) } /// Returns true iff w is on the path from u to v @@ -188,14 +189,13 @@ impl HLD { /// - Time: O(log n) /// - Space: O(1) pub fn kth_on_path(&self, u: usize, v: usize, k: usize) -> Option { - let mut dst_side = [0; 2]; - self.path(u, v, |range, u_anc| dst_side[u_anc as usize] += range.len()); - if k < dst_side[1] { - return self.kth_par(u, k); - } - let dst = dst_side[0] + dst_side[1] - !self.vals_edges as usize; - if k <= dst { - self.kth_par(v, dst - k) + let lca_d = self.d[self.lca(u, v)]; + let u_lca = self.d[u] - lca_d; + let v_lca = self.d[v] - lca_d; + if k <= u_lca { + self.kth_par(u, k) + } else if k <= u_lca + v_lca { + self.kth_par(v, u_lca + v_lca - k) } else { None } From 464ee82e80c9d0997e22a4d28c16c810f5454012 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Sat, 13 Jul 2024 10:59:49 -0500 Subject: [PATCH 2/7] fix other places --- src/graphs/lca.rs | 2 +- src/strings/suf_ary.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/graphs/lca.rs b/src/graphs/lca.rs index 4eb06d24..51417782 100644 --- a/src/graphs/lca.rs +++ b/src/graphs/lca.rs @@ -73,7 +73,7 @@ impl LCA { } let (mut le, mut ri) = (self.tin[u], self.tin[v]); if le > ri { - std::mem::swap(&mut le, &mut ri); + (le, ri) = (ri, le); } self.p[self.rmq.query(le + 1..ri + 1).1].unwrap() } diff --git a/src/strings/suf_ary.rs b/src/strings/suf_ary.rs index af6a217b..e4072ffe 100644 --- a/src/strings/suf_ary.rs +++ b/src/strings/suf_ary.rs @@ -108,7 +108,7 @@ impl SufAry { } let (mut le, mut ri) = (self.sa_inv[i1], self.sa_inv[i2]); if le > ri { - std::mem::swap(&mut le, &mut ri); + (le, ri) = (ri, le); } self.rmq.query(le..ri) } From a4ef9d154a5dd068a865995fe1c721ebf565db57 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Sat, 13 Jul 2024 11:03:16 -0500 Subject: [PATCH 3/7] remove old test --- ...p_on_tree_edges.rs => hld_jump_on_path.rs} | 0 examples/graphs/hld_jump_on_tree_nodes.rs | 59 ------------------- 2 files changed, 59 deletions(-) rename examples/graphs/{hld_jump_on_tree_edges.rs => hld_jump_on_path.rs} (100%) delete mode 100644 examples/graphs/hld_jump_on_tree_nodes.rs diff --git a/examples/graphs/hld_jump_on_tree_edges.rs b/examples/graphs/hld_jump_on_path.rs similarity index 100% rename from examples/graphs/hld_jump_on_tree_edges.rs rename to examples/graphs/hld_jump_on_path.rs diff --git a/examples/graphs/hld_jump_on_tree_nodes.rs b/examples/graphs/hld_jump_on_tree_nodes.rs deleted file mode 100644 index b1f770ed..00000000 --- a/examples/graphs/hld_jump_on_tree_nodes.rs +++ /dev/null @@ -1,59 +0,0 @@ -// verification-helper: PROBLEM https://judge.yosupo.jp/problem/jump_on_tree - -use proconio::input; -use programming_team_code_rust::graphs::hld::HLD; - -fn main() { - input! { - n: usize, - q: usize, - } - - let mut adj = vec![vec![]; n]; - for _ in 1..n { - input! { - u: usize, - v: usize - } - adj[u].push(v); - adj[v].push(u); - } - - let hld = HLD::new(&mut adj, false); - - fn dfs(u: usize, adj: &[Vec], d: &mut [usize]) { - for &v in &adj[u] { - d[v] = 1 + d[u]; - dfs(v, adj, d); - } - } - - let mut d = vec![0; n]; - dfs(0, &adj, &mut d); - - for _ in 0..q { - input! { - u: usize, - v: usize, - k: usize, - } - - let in_sub_naive = hld.kth_par(v, d[u].abs_diff(d[v])) == Some(u); - assert_eq!(in_sub_naive, hld.in_sub(u, v)); - - match hld.kth_on_path(u, v, k) { - Some(w) => { - assert!(k < hld.dist(u, v)); - assert!(hld.on_path(u, v, w)); - if w != u { - assert!(!hld.on_path(v, w, u)); - } - println!("{}", w); - } - None => { - assert!(k >= hld.dist(u, v)); - println!("-1"); - } - } - } -} From 2693bec383b10a8f5e65bcda8a654a10f16d9d56 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Sat, 13 Jul 2024 11:06:48 -0500 Subject: [PATCH 4/7] fix --- Cargo.toml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d3489dc4..7729e81d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -125,12 +125,8 @@ name = "hld_path_composite_yosupo" path = "examples/graphs/hld_path_composite_yosupo.rs" [[example]] -name = "hld_jump_on_tree_nodes" -path = "examples/graphs/hld_jump_on_tree_nodes.rs" - -[[example]] -name = "hld_jump_on_tree_edges" -path = "examples/graphs/hld_jump_on_tree_edges.rs" +name = "hld_jump_on_path" +path = "examples/graphs/hld_jump_on_path.rs" [[example]] name = "hopcroft_karp_yosupo" From b04a331611ecbb692c8b9ae2ff1b593c6400509a Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Sat, 13 Jul 2024 12:06:59 -0500 Subject: [PATCH 5/7] fix code cov --- examples/helpers/lis_pop.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/helpers/lis_pop.rs b/examples/helpers/lis_pop.rs index e506c1eb..d53b469b 100644 --- a/examples/helpers/lis_pop.rs +++ b/examples/helpers/lis_pop.rs @@ -22,6 +22,7 @@ fn main() { for _ in 0..100 { let mut lis = Lis::default(); let mut a = Vec::new(); + assert_eq!(lis.get_lis(), vec![]); for _ in 0..1000 { match rand::random::() % 3 { 0 => { From 5816c3ad02943cad4ee0970f40dbcf2de7023a0b Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Sat, 13 Jul 2024 12:47:01 -0500 Subject: [PATCH 6/7] trying this --- examples/helpers/lis_aizu.rs | 2 ++ examples/helpers/lis_pop.rs | 1 - examples/helpers/lis_yosupo.rs | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/helpers/lis_aizu.rs b/examples/helpers/lis_aizu.rs index 91b78f22..23c01216 100644 --- a/examples/helpers/lis_aizu.rs +++ b/examples/helpers/lis_aizu.rs @@ -11,6 +11,8 @@ fn main() { let mut lis = Lis::default(); + assert_eq!(lis.get_lis(), vec![]); + for elem in a { lis.push(elem); } diff --git a/examples/helpers/lis_pop.rs b/examples/helpers/lis_pop.rs index d53b469b..e506c1eb 100644 --- a/examples/helpers/lis_pop.rs +++ b/examples/helpers/lis_pop.rs @@ -22,7 +22,6 @@ fn main() { for _ in 0..100 { let mut lis = Lis::default(); let mut a = Vec::new(); - assert_eq!(lis.get_lis(), vec![]); for _ in 0..1000 { match rand::random::() % 3 { 0 => { diff --git a/examples/helpers/lis_yosupo.rs b/examples/helpers/lis_yosupo.rs index b25a583a..bf282d45 100644 --- a/examples/helpers/lis_yosupo.rs +++ b/examples/helpers/lis_yosupo.rs @@ -11,6 +11,8 @@ fn main() { let mut lis = Lis::default(); + assert_eq!(lis.get_lis(), vec![]); + for &elem in &a { lis.push(elem); } From 6754788e52332adfaf3f676e7f52429192be8138 Mon Sep 17 00:00:00 2001 From: Luke Videckis Date: Mon, 15 Jul 2024 16:49:10 -0500 Subject: [PATCH 7/7] fix code cov --- examples/graphs/hld_jump_on_path.rs | 3 +++ src/graphs/hld.rs | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/graphs/hld_jump_on_path.rs b/examples/graphs/hld_jump_on_path.rs index 3d8e6fbf..97de62eb 100644 --- a/examples/graphs/hld_jump_on_path.rs +++ b/examples/graphs/hld_jump_on_path.rs @@ -28,6 +28,9 @@ fn main() { k: usize, } + assert_eq!(hld.kth_par(u, hld.d[u]), Some(0)); + assert_eq!(hld.kth_par(u, hld.d[u] + 1), None); + match hld.kth_on_path(u, v, k) { Some(w) => { assert!(k <= hld.dist(u, v)); diff --git a/src/graphs/hld.rs b/src/graphs/hld.rs index 8a0695bf..c315a98a 100644 --- a/src/graphs/hld.rs +++ b/src/graphs/hld.rs @@ -33,7 +33,8 @@ pub struct HLD { pub p: Vec>, /// time in pub tin: Vec, - d: Vec, + /// depth + pub d: Vec, ord: Vec, siz: Vec, head: Vec,