Skip to content

Commit 47fa6f6

Browse files
committed
more ways to initialize and merge trees with DynamicArq
1 parent 1fc577d commit 47fa6f6

File tree

5 files changed

+88
-36
lines changed

5 files changed

+88
-36
lines changed

src/range_query/dynamic_arq.rs

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ impl<T: ArqSpec> DynamicArqNode<T> {
2424
Self {
2525
val,
2626
app: None,
27-
down: (0, 0),
27+
down: (usize::max_value(), usize::max_value()),
2828
}
2929
}
3030

@@ -50,31 +50,65 @@ pub struct DynamicArq<T: ArqSpec> {
5050
}
5151

5252
impl<T: ArqSpec> DynamicArq<T> {
53-
pub fn new(
54-
l_bound: i64,
55-
r_bound: i64,
56-
is_persistent: bool,
57-
initializer: Box<dyn Fn(i64, i64) -> T::M>,
58-
) -> (Self, ArqView) {
59-
let val = initializer(l_bound, r_bound);
60-
let nodes = vec![DynamicArqNode::new(val)];
61-
let arq = Self {
62-
nodes,
53+
/// Initializes the data structure without creating any nodes.
54+
/// The initializer f must satisfy: f(l, r) = T::op(f(l, m), f(m+1, r))
55+
pub fn new(is_persistent: bool, initializer: Box<dyn Fn(i64, i64) -> T::M>) -> Self {
56+
Self {
57+
nodes: vec![],
6358
is_persistent,
6459
initializer,
65-
};
66-
let root_view = (0, l_bound, r_bound);
67-
(arq, root_view)
60+
}
6861
}
6962

70-
pub fn new_with_identity(l_bound: i64, r_bound: i64, is_persistent: bool) -> (Self, ArqView) {
63+
/// Initializes the data structure without creating any nodes.
64+
pub fn new_with_identity(is_persistent: bool) -> Self {
7165
let initializer = Box::new(|_, _| T::identity());
72-
Self::new(l_bound, r_bound, is_persistent, initializer)
66+
Self::new(is_persistent, initializer)
67+
}
68+
69+
/// Lazily builds a tree over the range [l_bound, r_bound].
70+
pub fn build_using_initializer(&mut self, l_bound: i64, r_bound: i64) -> ArqView {
71+
let view = (self.nodes.len(), l_bound, r_bound);
72+
let val = (self.initializer)(l_bound, r_bound);
73+
self.nodes.push(DynamicArqNode::new(val));
74+
view
75+
}
76+
77+
/// Builds a tree whose leaves are set to a given non-empty slice.
78+
pub fn build_from_slice(&mut self, init_val: &[T::M]) -> ArqView {
79+
if init_val.len() == 1 {
80+
let view = (self.nodes.len(), 0, 0);
81+
let val = T::op(&T::identity(), &init_val[0]);
82+
self.nodes.push(DynamicArqNode::new(val));
83+
return view;
84+
}
85+
let m = (init_val.len() + 1) / 2;
86+
let (l_init, r_init) = init_val.split_at(m);
87+
let l_view = self.build_from_slice(l_init);
88+
let r_view = self.build_from_slice(r_init);
89+
self.merge_equal_sized(l_view, r_view)
90+
}
91+
92+
/// Merges two balanced subtrees into a single tree with a 0-indexed view.
93+
pub fn merge_equal_sized(&mut self, l_view: ArqView, r_view: ArqView) -> ArqView {
94+
let l_len = l_view.2 - l_view.1 + 1;
95+
let r_len = r_view.2 - r_view.1 + 1;
96+
assert!(l_len == r_len || l_len == r_len + 1);
97+
98+
let view = (self.nodes.len(), 0, l_len + r_len - 1);
99+
let root = DynamicArqNode {
100+
val: T::identity(),
101+
app: None,
102+
down: (l_view.0, r_view.0),
103+
};
104+
self.nodes.push(root);
105+
self.pull(view.0);
106+
view
73107
}
74108

75109
pub fn push(&mut self, (p, l, r): ArqView) -> (ArqView, ArqView) {
76110
let m = (l + r) / 2;
77-
if self.nodes[p].down.0 == 0 {
111+
if self.nodes[p].down.0 == usize::max_value() {
78112
let l_val = (self.initializer)(l, m);
79113
let r_val = (self.initializer)(m + 1, r);
80114
self.nodes.push(DynamicArqNode::new(l_val));

src/range_query/mod.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod test {
1313

1414
#[test]
1515
fn test_rmq() {
16-
let mut arq = StaticArq::<AssignMin>::new(vec![0; 10]);
16+
let mut arq = StaticArq::<AssignMin>::new(&[0; 10]);
1717

1818
assert_eq!(arq.query(0, 9), 0);
1919

@@ -27,7 +27,8 @@ mod test {
2727
#[test]
2828
fn test_dynamic_rmq() {
2929
let initializer = Box::new(|_, _| 0);
30-
let (mut arq, view) = DynamicArq::<AssignMin>::new(0, 9, false, initializer);
30+
let mut arq = DynamicArq::<AssignMin>::new(false, initializer);
31+
let view = arq.build_using_initializer(0, 9);
3132

3233
assert_eq!(arq.query(view, 0, 9), 0);
3334

@@ -41,7 +42,8 @@ mod test {
4142
#[test]
4243
fn test_persistent_rmq() {
4344
let initializer = Box::new(|_, _| 0);
44-
let (mut arq, mut view) = DynamicArq::<AssignMin>::new(0, 9, true, initializer);
45+
let mut arq = DynamicArq::<AssignMin>::new(true, initializer);
46+
let mut view = arq.build_using_initializer(0, 9);
4547

4648
let at_init = view;
4749
view = arq.modify(view, 2, 4, &-5);
@@ -56,7 +58,7 @@ mod test {
5658

5759
#[test]
5860
fn test_range_sum() {
59-
let mut arq = StaticArq::<AssignSum>::new(vec![(0, 1); 10]);
61+
let mut arq = StaticArq::<AssignSum>::new(&[(0, 1); 10]);
6062

6163
assert_eq!(arq.query(0, 9), (0, 10));
6264

@@ -70,7 +72,8 @@ mod test {
7072
#[test]
7173
fn test_dynamic_range_sum() {
7274
let initializer = Box::new(|l, r| (0, 1 + r - l));
73-
let (mut arq, view) = DynamicArq::<AssignSum>::new(0, 9, false, initializer);
75+
let mut arq = DynamicArq::<AssignSum>::new(false, initializer);
76+
let view = arq.build_using_initializer(0, 9);
7477

7578
assert_eq!(arq.query(view, 0, 9), (0, 10));
7679

@@ -83,7 +86,7 @@ mod test {
8386

8487
#[test]
8588
fn test_supply_demand() {
86-
let mut arq = StaticArq::<SupplyDemand>::new(vec![(0, 0, 0); 10]);
89+
let mut arq = StaticArq::<SupplyDemand>::new(&[(0, 0, 0); 10]);
8790

8891
arq.modify(1, 1, &(25, 100));
8992
arq.modify(3, 3, &(100, 30));
@@ -94,7 +97,8 @@ mod test {
9497

9598
#[test]
9699
fn test_dynamic_supply_demand() {
97-
let (mut arq, view) = DynamicArq::<SupplyDemand>::new_with_identity(0, 9, false);
100+
let mut arq = DynamicArq::<SupplyDemand>::new_with_identity(false);
101+
let view = arq.build_using_initializer(0, 9);
98102

99103
arq.modify(view, 1, 1, &(25, 100));
100104
arq.modify(view, 3, 3, &(100, 30));
@@ -106,7 +110,7 @@ mod test {
106110
#[test]
107111
fn test_binary_search_rmq() {
108112
let vec = vec![2, 1, 0, -1, -2, -3, -4, -5];
109-
let mut arq = StaticArq::<AssignMin>::new(vec);
113+
let mut arq = StaticArq::<AssignMin>::new(&vec);
110114
let first_neg = static_arq::first_negative(&mut arq);
111115

112116
arq.modify(3, 7, &0);
@@ -116,11 +120,26 @@ mod test {
116120
assert_eq!(first_neg_zeros, None);
117121
}
118122

123+
#[test]
124+
fn test_dynslice_binary_search_rmq() {
125+
let vec = vec![2, 1, 0, -1, -2, -3, -4, -5];
126+
let mut arq = DynamicArq::<AssignMin>::new_with_identity(false);
127+
let view = arq.build_from_slice(&vec);
128+
let first_neg = dynamic_arq::first_negative(&mut arq, view);
129+
130+
arq.modify(view, 3, 7, &0);
131+
let first_neg_zeros = dynamic_arq::first_negative(&mut arq, view);
132+
133+
assert_eq!(first_neg, Some(3));
134+
assert_eq!(first_neg_zeros, None);
135+
}
136+
119137
#[test]
120138
fn test_dynamic_binary_search_rmq() {
121139
let initializer = Box::new(|_, r| 2 - r);
122140
let (l_bound, r_bound) = (0, 1_000_000_000_000_000_000);
123-
let (mut arq, view) = DynamicArq::<AssignMin>::new(l_bound, r_bound, false, initializer);
141+
let mut arq = DynamicArq::<AssignMin>::new(false, initializer);
142+
let view = arq.build_using_initializer(l_bound, r_bound);
124143
let first_neg = dynamic_arq::first_negative(&mut arq, view);
125144

126145
arq.modify(view, 2, r_bound - 1, &0);

src/range_query/static_arq.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ pub struct StaticArq<T: ArqSpec> {
2121

2222
impl<T: ArqSpec> StaticArq<T> {
2323
/// Initializes a static balanced tree on top of the given sequence.
24-
pub fn new(init_val: Vec<T::M>) -> Self {
24+
pub fn new(init_val: &[T::M]) -> Self {
2525
let size = init_val.len();
2626
let mut val = (0..size).map(|_| T::identity()).collect::<Vec<_>>();
27-
val.append(&mut { init_val });
27+
val.extend(init_val.iter().map(|v| T::op(&T::identity(), v)));
2828
let app = vec![None; size];
2929

3030
let mut arq = Self { val, app };

src/scanner.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ mod test {
8686

8787
#[test]
8888
fn test_in_memory_io() {
89-
let cursor = io::Cursor::new("50 8");
90-
let mut scan = Scanner::new(cursor);
89+
let input = "50 8".as_bytes();
90+
let mut scan = Scanner::new(input);
9191
let mut out = String::new();
9292
use std::fmt::Write; // needed for writeln!()
9393

@@ -100,8 +100,8 @@ mod test {
100100

101101
#[test]
102102
fn test_in_memory_unsafe() {
103-
let cursor = io::Cursor::new("50 8");
104-
let mut scan = UnsafeScanner::new(cursor);
103+
let input = "50 8".as_bytes();
104+
let mut scan = UnsafeScanner::new(input);
105105
let mut out = String::new();
106106
use std::fmt::Write; // needed for writeln!()
107107

tests/codeforces343d.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Solves [Water Tree](http://codeforces.com/contest/343/problem/D).
22
//! To make a self-contained file for contest submission, dump each desired
33
//! module's contents directly here instead of the use statements.
4-
//! Also, replace io::Cursor with io::stdin as shown in scanner.rs.
4+
//! Also, use the commented code in main() to employ standard I/O.
55
extern crate contest_algorithms;
66
use contest_algorithms::graph::Graph;
77
use contest_algorithms::range_query::{specs::AssignSum, StaticArq};
@@ -62,8 +62,7 @@ fn dfs(
6262
#[test]
6363
fn main() {
6464
use std::fmt::Write;
65-
let cursor = std::io::Cursor::new(SAMPLE_INPUT);
66-
let mut scan = Scanner::new(cursor);
65+
let mut scan = Scanner::new(SAMPLE_INPUT.as_bytes());
6766
let mut out = String::new();
6867
/* To read/write with stdin/stdout instead:
6968
use std::io::{self, Write};
@@ -85,7 +84,7 @@ fn main() {
8584
let mut p = vec![0; n];
8685
dfs(&tree, 0, &mut l, &mut r, &mut p, &mut 0);
8786

88-
let mut arq = StaticArq::<AssignSum>::new(vec![(0, 1); n + 1]);
87+
let mut arq = StaticArq::<AssignSum>::new(&vec![(0, 1); n + 1]);
8988
let q = scan.token::<usize>();
9089
for _ in 0..q {
9190
let c = scan.token::<usize>();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy