Skip to content

Commit b9afd08

Browse files
Merge branch 'main' into compress_tree
2 parents 69c561c + d3a29c7 commit b9afd08

File tree

15 files changed

+377
-91
lines changed

15 files changed

+377
-91
lines changed

Cargo.toml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,8 @@ name = "hld_path_composite_yosupo"
125125
path = "examples/graphs/hld_path_composite_yosupo.rs"
126126

127127
[[example]]
128-
name = "hld_jump_on_tree_nodes"
129-
path = "examples/graphs/hld_jump_on_tree_nodes.rs"
130-
131-
[[example]]
132-
name = "hld_jump_on_tree_edges"
133-
path = "examples/graphs/hld_jump_on_tree_edges.rs"
128+
name = "hld_jump_on_path"
129+
path = "examples/graphs/hld_jump_on_path.rs"
134130

135131
[[example]]
136132
name = "hopcroft_karp_yosupo"
@@ -201,8 +197,16 @@ name = "lis_yosupo"
201197
path = "examples/helpers/lis_yosupo.rs"
202198

203199
[[example]]
204-
name = "lis_pop"
205-
path = "examples/helpers/lis_pop.rs"
200+
name = "lis_handmade"
201+
path = "examples/helpers/lis_handmade.rs"
202+
203+
[[example]]
204+
name = "range_container_aizu"
205+
path = "examples/data_structures/range_container_aizu.rs"
206+
207+
[[example]]
208+
name = "range_container_handmade"
209+
path = "examples/data_structures/range_container_handmade.rs"
206210

207211
[[example]]
208212
name = "mono_st"
@@ -230,4 +234,8 @@ path = "examples/data_structures/disjoint_rmq_non_commutative.rs"
230234

231235
[[example]]
232236
name = "lca_rmq_next_on_path"
233-
path = "examples/graphs/lca_rmq_next_on_path.rs"
237+
path = "examples/graphs/lca_rmq_next_on_path.rs"
238+
239+
[[example]]
240+
name = "linear_rmq"
241+
path = "examples/data_structures/linear_rmq.rs"

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
- tests are named `[algo].rs`
33
- use both yosupo and aizu to test whenever possible because bugs have existed on one of the sites but not the other
44
- when using both sites name the files `[algo]_yosupo.rs` and `[algo]_aizu.rs`
5+
- when there's no problem to test on, test on [hello world](https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/all/ITP1_1_A) and name the files `[algo]_handmade.rs`
56
- when only testing a specific function or componenet of some algorithm name the file `[algo]_[component].rs`
67

78
# Documentation Guidelines
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/staticrmq
2+
3+
use proconio::input;
4+
use programming_team_code_rust::data_structures::linear_rmq::LinearRMQ;
5+
6+
fn main() {
7+
input! {
8+
n: usize,
9+
q: usize,
10+
a: [usize; n],
11+
}
12+
13+
let rmq = LinearRMQ::new(&a, |&x, &y| x.lt(&y));
14+
for _ in 0..q {
15+
input! {
16+
le: usize,
17+
ri: usize,
18+
}
19+
let idx_min = rmq.query_idx(le..ri);
20+
assert!((le..ri).contains(&idx_min));
21+
let res = rmq.query(le..ri);
22+
assert_eq!(a[idx_min], *res);
23+
println!("{}", res);
24+
}
25+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/DSL_2_D
2+
3+
use proconio::input;
4+
use programming_team_code_rust::data_structures::range_container::RangeContainer;
5+
6+
fn main() {
7+
input! {
8+
n: usize,
9+
q: usize,
10+
}
11+
let mut rc = RangeContainer::default();
12+
let mut to_value = vec![i32::MAX; 2 * n + 2];
13+
rc.insert_range(0..(2 * n + 1) as i32);
14+
15+
for _ in 0..q {
16+
input! {
17+
kind: usize,
18+
}
19+
match kind {
20+
0 => {
21+
input! {
22+
le: i32,
23+
ri: i32,
24+
x: i32,
25+
}
26+
let le = 2 * le;
27+
let ri = 2 * ri;
28+
let save_range = rc.get_range(ri + 2).unwrap();
29+
let save_value = to_value[save_range.start as usize];
30+
rc.remove_range(le - 1..ri + 2);
31+
rc.insert_range(le..ri + 1);
32+
let save_range = rc.get_range(ri + 2).unwrap();
33+
to_value[save_range.start as usize] = save_value;
34+
to_value[le as usize] = x;
35+
}
36+
_ => {
37+
input! {
38+
index: i32,
39+
}
40+
let range_containing = rc.get_range(2 * index).unwrap();
41+
println!("{}", to_value[range_containing.start as usize]);
42+
}
43+
}
44+
}
45+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/all/ITP1_1_A
2+
3+
use programming_team_code_rust::data_structures::range_container::RangeContainer;
4+
use rand::{thread_rng, Rng};
5+
use std::collections::BTreeMap;
6+
7+
fn main() {
8+
let mut rng = thread_rng();
9+
for _ in 0..100 {
10+
let max_n = rng.gen_range(1..100);
11+
let mut vis = vec![false; max_n + 1];
12+
let mut rc = RangeContainer::default();
13+
for _ in 0..100 {
14+
let mut le = rng.gen_range(0..=max_n);
15+
let mut ri = rng.gen_range(0..=max_n);
16+
if le > ri {
17+
(le, ri) = (ri, le);
18+
}
19+
match rng.gen_range(0..2) {
20+
0 => {
21+
rc.insert_range(le as i32..ri as i32);
22+
for elem in vis.iter_mut().take(ri).skip(le) {
23+
*elem = true;
24+
}
25+
}
26+
_ => {
27+
rc.remove_range(le as i32..ri as i32);
28+
for elem in vis.iter_mut().take(ri).skip(le) {
29+
*elem = false;
30+
}
31+
}
32+
}
33+
let mut to_end = vec![None; max_n + 1];
34+
for i in (0..max_n).rev() {
35+
if vis[i] && !vis[i + 1] {
36+
to_end[i] = Some(i + 1);
37+
} else if vis[i] {
38+
to_end[i] = to_end[i + 1];
39+
}
40+
}
41+
let mut naive_mp = BTreeMap::<i32, i32>::new();
42+
let mut start = None;
43+
for i in 0..max_n + 1 {
44+
if vis[i] {
45+
if start.is_none() {
46+
start = Some(i);
47+
}
48+
assert_eq!(
49+
rc.get_range(i as i32).unwrap(),
50+
start.unwrap() as i32..to_end[i].unwrap() as i32
51+
);
52+
} else {
53+
assert_eq!(rc.get_range(i as i32), None);
54+
if let Some(curr_start) = start {
55+
naive_mp.insert(curr_start as i32, i as i32);
56+
}
57+
start = None;
58+
}
59+
}
60+
assert_eq!(rc.mp, naive_mp);
61+
}
62+
}
63+
println!("Hello World");
64+
}

examples/graphs/hld_jump_on_tree_edges.rs renamed to examples/graphs/hld_jump_on_path.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ fn main() {
2828
k: usize,
2929
}
3030

31+
assert_eq!(hld.kth_par(u, hld.d[u]), Some(0));
32+
assert_eq!(hld.kth_par(u, hld.d[u] + 1), None);
33+
3134
match hld.kth_on_path(u, v, k) {
3235
Some(w) => {
3336
assert!(k <= hld.dist(u, v));

examples/graphs/hld_jump_on_tree_nodes.rs

Lines changed: 0 additions & 59 deletions
This file was deleted.

examples/helpers/lis_pop.rs renamed to examples/helpers/lis_handmade.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/all/ITP1_1_A
22

33
use programming_team_code_rust::helpers::lis::Lis;
4+
use rand::{thread_rng, Rng};
45

56
fn lis_quadratic(a: &[i32]) -> usize {
67
let n = a.len();
@@ -19,13 +20,14 @@ fn lis_quadratic(a: &[i32]) -> usize {
1920
}
2021

2122
fn main() {
23+
let mut rng = thread_rng();
2224
for _ in 0..100 {
2325
let mut lis = Lis::default();
2426
let mut a = Vec::new();
2527
for _ in 0..1000 {
26-
match rand::random::<u8>() % 3 {
28+
match rng.gen_range(0..3) {
2729
0 => {
28-
let new_num = rand::random::<i32>();
30+
let new_num = rng.r#gen();
2931
lis.push(new_num);
3032
a.push(new_num);
3133
}

src/data_structures/linear_rmq.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//! # Linear Range Minimum Query
2+
3+
/// # Example
4+
/// ```
5+
/// use programming_team_code_rust::data_structures::linear_rmq::LinearRMQ;
6+
///
7+
/// let a = [1, 0, 2, 0, 3];
8+
/// let rmq = LinearRMQ::new(&a, |&x, &y| x.lt(&y)); // lt -> right-most min
9+
/// // le -> left-most min
10+
/// // gt -> right-most max
11+
/// // ge -> left-most max
12+
/// assert_eq!(rmq.query_idx(0..5), 3);
13+
/// assert_eq!(*rmq.query(1..5), 0);
14+
/// ```
15+
pub struct LinearRMQ<T, F> {
16+
a: Vec<T>,
17+
cmp: F,
18+
head: Vec<usize>,
19+
t: Vec<(usize, usize)>,
20+
}
21+
22+
impl<T: Clone, F: Fn(&T, &T) -> bool> LinearRMQ<T, F> {
23+
/// Create a new LinearRMQ instance
24+
///
25+
/// # Complexity (n = a.len())
26+
/// - Time: O(n)
27+
/// - Space: O(n)
28+
pub fn new(a: &[T], cmp: F) -> Self {
29+
let mut head = vec![0; a.len() + 1];
30+
let mut t = vec![(0, 0); a.len()];
31+
let mut st = vec![usize::MAX];
32+
for i in 0..=a.len() {
33+
let mut prev = usize::MAX;
34+
while *st.last().unwrap() != usize::MAX
35+
&& (i == a.len() || !cmp(&a[*st.last().unwrap()], &a[i]))
36+
{
37+
if prev != usize::MAX {
38+
head[prev] = *st.last().unwrap();
39+
}
40+
let pw2 = 1 << (st[st.len() - 2].wrapping_add(1) ^ i).ilog2();
41+
prev = i & 0_usize.wrapping_sub(pw2);
42+
t[*st.last().unwrap()].0 = prev;
43+
st.pop();
44+
t[(*st.last().unwrap()).wrapping_add(1)].1 |= pw2;
45+
}
46+
if prev != usize::MAX {
47+
head[prev] = i;
48+
}
49+
st.push(i);
50+
}
51+
for i in 1..a.len() {
52+
t[i].1 =
53+
(t[i].1 | t[i - 1].1) & 0_usize.wrapping_sub(t[i].0 & 0_usize.wrapping_sub(t[i].0));
54+
}
55+
Self {
56+
a: a.to_vec(),
57+
cmp,
58+
head,
59+
t,
60+
}
61+
}
62+
63+
/// Gets the index of min/max of range
64+
///
65+
/// # Complexity
66+
/// - Time: O(1)
67+
/// - Space: O(1)
68+
pub fn query_idx(&self, range: std::ops::Range<usize>) -> usize {
69+
assert!(!range.is_empty());
70+
let (mut le, mut ri) = (range.start, range.end - 1);
71+
let j = self.t[le].1
72+
& self.t[ri].1
73+
& 0_usize.wrapping_sub(1 << ((self.t[le].0 ^ self.t[ri].0) | 1).ilog2());
74+
let lift = |u: usize, mut k: usize| -> usize {
75+
if k == 0 {
76+
u
77+
} else {
78+
k = 1 << k.ilog2();
79+
self.head[self.t[u].0 & 0_usize.wrapping_sub(k) | k]
80+
}
81+
};
82+
le = lift(le, self.t[le].1 ^ j);
83+
ri = lift(ri, self.t[ri].1 ^ j);
84+
if (self.cmp)(&self.a[le], &self.a[ri]) {
85+
le
86+
} else {
87+
ri
88+
}
89+
}
90+
91+
/// Gets the min/max of range
92+
///
93+
/// # Complexity
94+
/// - Time: O(1)
95+
/// - Space: O(1)
96+
pub fn query(&self, range: std::ops::Range<usize>) -> &T {
97+
&self.a[self.query_idx(range)]
98+
}
99+
}

src/data_structures/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ pub mod binary_trie;
33
pub mod disjoint_rmq;
44
pub mod fenwick;
55
pub mod lazy_seg_tree;
6+
pub mod linear_rmq;
7+
pub mod range_container;
68
pub mod rmq;
79
pub mod seg_tree;
810
pub mod trie;

0 commit comments

Comments
 (0)