Skip to content

Commit 9680b5c

Browse files
authored
Range container (#87)
* saving progress * finish insert * rename * finished impl * finished test, need to fix some bugs tho * saving progress * ACs!!! * progress * fix clippy * fix nit * clean * rename * nit * nit * another nit * better var names * more nits * finished docs * rename * raname * wording nit * nit * nits * saving progress * another assert * fix clippy * nit * correct doc * switch stress to handmade * change readme too * switch to templatizing --------- Co-authored-by: Luke Videckis <lukevideckis@gmail.com>
1 parent 0f8e5bd commit 9680b5c

File tree

7 files changed

+219
-5
lines changed

7 files changed

+219
-5
lines changed

Cargo.toml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,16 @@ name = "lis_yosupo"
201201
path = "examples/helpers/lis_yosupo.rs"
202202

203203
[[example]]
204-
name = "lis_pop"
205-
path = "examples/helpers/lis_pop.rs"
204+
name = "lis_handmade"
205+
path = "examples/helpers/lis_handmade.rs"
206+
207+
[[example]]
208+
name = "range_container_aizu"
209+
path = "examples/helpers/range_container_aizu.rs"
210+
211+
[[example]]
212+
name = "range_container_handmade"
213+
path = "examples/helpers/range_container_handmade.rs"
206214

207215
[[example]]
208216
name = "mono_st"
@@ -226,4 +234,4 @@ path = "examples/data_structures/disjoint_rmq_non_commutative.rs"
226234

227235
[[example]]
228236
name = "lca_rmq_next_on_path"
229-
path = "examples/graphs/lca_rmq_next_on_path.rs"
237+
path = "examples/graphs/lca_rmq_next_on_path.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

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
}
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::helpers::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: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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::helpers::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+
ri += 1;
20+
match rng.gen_range(0..2) {
21+
0 => {
22+
rc.insert_range(le as i32..ri as i32);
23+
for elem in vis.iter_mut().take(ri).skip(le) {
24+
*elem = true;
25+
}
26+
}
27+
_ => {
28+
rc.remove_range(le as i32..ri as i32);
29+
for elem in vis.iter_mut().take(ri).skip(le) {
30+
*elem = false;
31+
}
32+
}
33+
}
34+
let mut to_end = vec![None; max_n + 1];
35+
for i in (0..max_n).rev() {
36+
if vis[i] && !vis[i + 1] {
37+
to_end[i] = Some(i + 1);
38+
} else if vis[i] {
39+
to_end[i] = to_end[i + 1];
40+
}
41+
}
42+
let mut naive_mp = BTreeMap::<i32, i32>::new();
43+
let mut start = None;
44+
for i in 0..max_n + 1 {
45+
if vis[i] {
46+
if start.is_none() {
47+
start = Some(i);
48+
}
49+
assert_eq!(
50+
rc.get_range(i as i32).unwrap(),
51+
start.unwrap() as i32..to_end[i].unwrap() as i32
52+
);
53+
} else {
54+
assert_eq!(rc.get_range(i as i32), None);
55+
if let Some(curr_start) = start {
56+
naive_mp.insert(curr_start as i32, i as i32);
57+
}
58+
start = None;
59+
}
60+
}
61+
assert_eq!(rc.mp, naive_mp);
62+
}
63+
}
64+
println!("Hello World");
65+
}

src/helpers/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! # Helpers
22
pub mod compress;
33
pub mod lis;
4+
pub mod range_container;
45
pub mod unsafe_recursive_closure;

src/helpers/range_container.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//! # Range Container
2+
3+
use std::collections::BTreeMap;
4+
use std::ops::Range;
5+
6+
/// # Example
7+
/// ```
8+
/// use programming_team_code_rust::helpers::range_container::RangeContainer;
9+
///
10+
/// let mut rc = RangeContainer::default();
11+
/// rc.insert_range(-2..2);
12+
/// rc.insert_range(2..3);
13+
/// assert_eq!(rc.get_range(0), Some(-2..3));
14+
/// assert_eq!(rc.get_range(3), None);
15+
/// rc.remove_range(-1..1);
16+
///
17+
/// assert_eq!(rc.get_range(-2), Some(-2..-1));
18+
/// assert_eq!(rc.get_range(2), Some(1..3));
19+
/// ```
20+
#[derive(Default)]
21+
pub struct RangeContainer<T> {
22+
/// an entry le -> ri represents a range [le, ri)
23+
/// invariant: previous_ri < current_le
24+
pub mp: BTreeMap<T, T>,
25+
}
26+
27+
impl<T: Copy + Ord> RangeContainer<T> {
28+
fn remove(&mut self, range: &Range<T>) -> Option<T> {
29+
let mut last_ri = None;
30+
for (le, ri) in self
31+
.mp
32+
.range(range.start..=range.end)
33+
.map(|(&le, &ri)| (le, ri))
34+
.collect::<Vec<_>>()
35+
{
36+
self.mp.remove(&le);
37+
last_ri = Some(ri);
38+
}
39+
last_ri
40+
}
41+
42+
/// Inserts a range into the container
43+
///
44+
/// # Complexity
45+
/// - Time: O(log n) ammortized
46+
/// - Space: O(1) ammortized
47+
pub fn insert_range(&mut self, mut range: Range<T>) {
48+
if let Some(last_ri) = self.remove(&range) {
49+
range.end = std::cmp::max(range.end, last_ri);
50+
}
51+
if let Some((_, ri)) = self.mp.range_mut(..range.start).next_back() {
52+
if *ri >= range.start {
53+
*ri = std::cmp::max(*ri, range.end);
54+
return;
55+
}
56+
}
57+
self.mp.insert(range.start, range.end);
58+
}
59+
60+
/// Removes a range from the container
61+
///
62+
/// # Complexity
63+
/// - Time: O(log n) ammortized
64+
/// - Space: O(1) ammortized
65+
pub fn remove_range(&mut self, range: Range<T>) {
66+
if let Some(last_ri) = self.remove(&range) {
67+
if range.end < last_ri {
68+
self.mp.insert(range.end, last_ri);
69+
}
70+
}
71+
if let Some((_, ri)) = self.mp.range_mut(..range.start).next_back() {
72+
let ri = std::mem::replace(ri, std::cmp::min(*ri, range.start));
73+
if range.end < ri {
74+
self.mp.insert(range.end, ri);
75+
}
76+
}
77+
}
78+
79+
/// Gets range containing idx
80+
///
81+
/// # Complexity
82+
/// - Time: O(log n)
83+
/// - Space: O(1)
84+
pub fn get_range(&self, idx: T) -> Option<Range<T>> {
85+
if let Some((&le, &ri)) = self.mp.range(..=idx).next_back() {
86+
if idx < ri {
87+
return Some(le..ri);
88+
}
89+
}
90+
None
91+
}
92+
}

0 commit comments

Comments
 (0)