Skip to content

Commit 42db8cc

Browse files
committed
Cleaning up redundant pieces of DynamicArq, making it pretty much the best segtree you've ever seen :D
1 parent 47fa6f6 commit 42db8cc

File tree

4 files changed

+89
-111
lines changed

4 files changed

+89
-111
lines changed

src/range_query/dynamic_arq.rs

Lines changed: 63 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,31 @@ pub struct DynamicArqNode<T: ArqSpec> {
88
down: (usize, usize),
99
}
1010

11-
// TODO: can this be replaced by a #[derive(Clone)]?
11+
// TODO: in a future Rust version, this might be replaced by a #[derive(Clone)]
1212
impl<T: ArqSpec> Clone for DynamicArqNode<T> {
1313
fn clone(&self) -> Self {
1414
Self {
15-
val: T::op(&T::identity(), &self.val),
15+
val: self.val.clone(),
1616
app: self.app.clone(),
1717
down: self.down,
1818
}
1919
}
2020
}
2121

22-
impl<T: ArqSpec> DynamicArqNode<T> {
23-
pub fn new(val: T::M) -> Self {
22+
impl<T: ArqSpec> Default for DynamicArqNode<T> {
23+
fn default() -> Self {
2424
Self {
25-
val,
25+
val: T::identity(),
2626
app: None,
2727
down: (usize::max_value(), usize::max_value()),
2828
}
2929
}
30+
}
3031

31-
fn apply(&mut self, f: &T::F, is_leaf: bool) {
32+
impl<T: ArqSpec> DynamicArqNode<T> {
33+
fn apply(&mut self, f: &T::F, size: i64) {
3234
self.val = T::apply(f, &self.val);
33-
if !is_leaf {
35+
if size > 1 {
3436
let h = match self.app {
3537
Some(ref g) => T::compose(f, g),
3638
None => f.clone(),
@@ -40,87 +42,69 @@ impl<T: ArqSpec> DynamicArqNode<T> {
4042
}
4143
}
4244

43-
pub type ArqView = (usize, i64, i64);
45+
pub type ArqView = (usize, i64);
4446

4547
/// A dynamic, and optionally persistent, associative range query data structure.
4648
pub struct DynamicArq<T: ArqSpec> {
4749
nodes: Vec<DynamicArqNode<T>>,
4850
is_persistent: bool,
49-
initializer: Box<dyn Fn(i64, i64) -> T::M>,
5051
}
5152

5253
impl<T: ArqSpec> DynamicArq<T> {
5354
/// 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 {
55+
pub fn new(is_persistent: bool) -> Self {
5656
Self {
5757
nodes: vec![],
5858
is_persistent,
59-
initializer,
6059
}
6160
}
6261

63-
/// Initializes the data structure without creating any nodes.
64-
pub fn new_with_identity(is_persistent: bool) -> Self {
65-
let initializer = Box::new(|_, _| T::identity());
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
62+
/// Lazily builds a tree initialized to the identity.
63+
pub fn build_from_identity(&mut self, size: i64) -> ArqView {
64+
self.nodes.push(DynamicArqNode::default());
65+
(self.nodes.len() - 1, size)
7566
}
7667

7768
/// Builds a tree whose leaves are set to a given non-empty slice.
7869
pub fn build_from_slice(&mut self, init_val: &[T::M]) -> ArqView {
7970
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;
71+
let mut root = DynamicArqNode::default();
72+
root.val = init_val[0].clone();
73+
self.nodes.push(root);
74+
(self.nodes.len() - 1, 1)
75+
} else {
76+
let ls = init_val.len() / 2;
77+
let (l_init, r_init) = init_val.split_at(ls);
78+
let l_view = self.build_from_slice(l_init);
79+
let r_view = self.build_from_slice(r_init);
80+
self.merge_equal_sized(l_view, r_view)
8481
}
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)
9082
}
9183

9284
/// 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-
};
85+
pub fn merge_equal_sized(&mut self, (lp, ls): ArqView, (rp, rs): ArqView) -> ArqView {
86+
assert!(ls == rs || ls + 1 == rs);
87+
let p = self.nodes.len();
88+
let mut root = DynamicArqNode::default();
89+
root.down = (lp, rp);
10490
self.nodes.push(root);
105-
self.pull(view.0);
106-
view
91+
self.pull(p);
92+
(p, ls + rs)
10793
}
10894

109-
pub fn push(&mut self, (p, l, r): ArqView) -> (ArqView, ArqView) {
110-
let m = (l + r) / 2;
95+
pub fn push(&mut self, (p, s): ArqView) -> (ArqView, ArqView) {
11196
if self.nodes[p].down.0 == usize::max_value() {
112-
let l_val = (self.initializer)(l, m);
113-
let r_val = (self.initializer)(m + 1, r);
114-
self.nodes.push(DynamicArqNode::new(l_val));
115-
self.nodes.push(DynamicArqNode::new(r_val));
97+
self.nodes.push(DynamicArqNode::default());
98+
self.nodes.push(DynamicArqNode::default());
11699
self.nodes[p].down = (self.nodes.len() - 2, self.nodes.len() - 1)
117100
};
118101
let (lp, rp) = self.nodes[p].down;
102+
let ls = s / 2;
119103
if let Some(ref f) = self.nodes[p].app.take() {
120-
self.nodes[lp].apply(f, l == m);
121-
self.nodes[rp].apply(f, m + 1 == r);
104+
self.nodes[lp].apply(f, ls);
105+
self.nodes[rp].apply(f, s - ls);
122106
}
123-
((lp, l, m), (rp, m + 1, r))
107+
((lp, ls), (rp, s - ls))
124108
}
125109

126110
fn pull(&mut self, p: usize) {
@@ -130,48 +114,50 @@ impl<T: ArqSpec> DynamicArq<T> {
130114
self.nodes[p].val = T::op(left_val, right_val);
131115
}
132116

133-
fn clone_node(&mut self, p: usize) -> usize {
117+
fn clone_node(&mut self, p_orig: usize) -> usize {
134118
if self.is_persistent {
135-
let node = self.nodes[p].clone();
119+
let node = self.nodes[p_orig].clone();
136120
self.nodes.push(node);
137121
self.nodes.len() - 1
138122
} else {
139-
p
123+
p_orig
140124
}
141125
}
142126

143127
/// Applies the endomorphism f to all entries from l to r, inclusive.
144128
/// If l == r, the updates are eager. Otherwise, they are lazy.
145129
pub fn modify(&mut self, view: ArqView, l: i64, r: i64, f: &T::F) -> ArqView {
146-
let (p, cl, cr) = view;
147-
if r < cl || cr < l {
130+
let (p_orig, s) = view;
131+
if r < 0 || s - 1 < l {
148132
view
149-
} else if l <= cl && cr <= r /* && self.l == self.r forces eager */ {
150-
let p_clone = self.clone_node(p);
151-
self.nodes[p_clone].apply(f, l == r);
152-
(p_clone, cl, cr)
133+
} else if l <= 0 && s - 1 <= r {
134+
let p_clone = self.clone_node(p_orig);
135+
self.nodes[p_clone].apply(f, s);
136+
(p_clone, s)
153137
} else {
154138
let (l_view, r_view) = self.push(view);
155-
let p_clone = self.clone_node(p);
139+
let ls = l_view.1;
140+
let p_clone = self.clone_node(p_orig);
156141
let lp_clone = self.modify(l_view, l, r, f).0;
157-
let rp_clone = self.modify(r_view, l, r, f).0;
142+
let rp_clone = self.modify(r_view, l - ls, r - ls, f).0;
158143
self.nodes[p_clone].down = (lp_clone, rp_clone);
159144
self.pull(p_clone);
160-
(p_clone, cl, cr)
145+
(p_clone, s)
161146
}
162147
}
163148

164149
/// Returns the aggregate range query on all entries from l to r, inclusive.
165150
pub fn query(&mut self, view: ArqView, l: i64, r: i64) -> T::M {
166-
let (p, cl, cr) = view;
167-
if r < cl || cr < l {
151+
let (p, s) = view;
152+
if r < 0 || s - 1 < l {
168153
T::identity()
169-
} else if l <= cl && cr <= r {
170-
T::op(&T::identity(), &self.nodes[p].val)
154+
} else if l <= 0 && s - 1 <= r {
155+
self.nodes[p].val.clone()
171156
} else {
172157
let (l_view, r_view) = self.push(view);
158+
let ls = l_view.1;
173159
let l_agg = self.query(l_view, l, r);
174-
let r_agg = self.query(r_view, l, r);
160+
let r_agg = self.query(r_view, l - ls, r - ls);
175161
T::op(&l_agg, &r_agg)
176162
}
177163
}
@@ -180,16 +166,16 @@ impl<T: ArqSpec> DynamicArq<T> {
180166
/// An example of binary search on the tree of a DynamicArq.
181167
/// The tree may have any size, not necessarily a power of two.
182168
pub fn first_negative(arq: &mut DynamicArq<super::specs::AssignMin>, view: ArqView) -> Option<i64> {
183-
let (p, cl, cr) = view;
184-
if cl == cr {
185-
Some(cl).filter(|_| arq.nodes[p].val < 0)
169+
let (p, s) = view;
170+
if s == 1 {
171+
Some(0).filter(|_| arq.nodes[p].val < 0)
186172
} else {
187173
let (l_view, r_view) = arq.push(view);
188-
let lp = l_view.0;
174+
let (lp, ls) = l_view;
189175
if arq.nodes[lp].val < 0 {
190176
first_negative(arq, l_view)
191177
} else {
192-
first_negative(arq, r_view)
178+
first_negative(arq, r_view).map(|x| ls + x)
193179
}
194180
}
195181
}

src/range_query/mod.rs

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ mod test {
2626

2727
#[test]
2828
fn test_dynamic_rmq() {
29-
let initializer = Box::new(|_, _| 0);
30-
let mut arq = DynamicArq::<AssignMin>::new(false, initializer);
31-
let view = arq.build_using_initializer(0, 9);
29+
let mut arq = DynamicArq::<AssignMin>::new(false);
30+
let view = arq.build_from_slice(&[0; 10]);
3231

3332
assert_eq!(arq.query(view, 0, 9), 0);
3433

@@ -41,9 +40,8 @@ mod test {
4140

4241
#[test]
4342
fn test_persistent_rmq() {
44-
let initializer = Box::new(|_, _| 0);
45-
let mut arq = DynamicArq::<AssignMin>::new(true, initializer);
46-
let mut view = arq.build_using_initializer(0, 9);
43+
let mut arq = DynamicArq::<AssignMin>::new(true);
44+
let mut view = arq.build_from_slice(&[0; 10]);
4745

4846
let at_init = view;
4947
view = arq.modify(view, 2, 4, &-5);
@@ -56,6 +54,19 @@ mod test {
5654
assert_eq!(arq.query(view, 0, 9), -3);
5755
}
5856

57+
#[test]
58+
fn test_huge_rmq() {
59+
let quintillion = 1_000_000_000_000_000_000;
60+
let mut arq = DynamicArq::<AssignMin>::new(false);
61+
let view = arq.build_from_identity(9 * quintillion + 1);
62+
63+
arq.modify(view, 2 * quintillion, 4 * quintillion, &-5);
64+
arq.modify(view, 5 * quintillion, 7 * quintillion, &-3);
65+
arq.modify(view, 1 * quintillion, 6 * quintillion, &1);
66+
67+
assert_eq!(arq.query(view, 0, 9 * quintillion), -3);
68+
}
69+
5970
#[test]
6071
fn test_range_sum() {
6172
let mut arq = StaticArq::<AssignSum>::new(&[(0, 1); 10]);
@@ -71,9 +82,8 @@ mod test {
7182

7283
#[test]
7384
fn test_dynamic_range_sum() {
74-
let initializer = Box::new(|l, r| (0, 1 + r - l));
75-
let mut arq = DynamicArq::<AssignSum>::new(false, initializer);
76-
let view = arq.build_using_initializer(0, 9);
85+
let mut arq = DynamicArq::<AssignSum>::new(false);
86+
let view = arq.build_from_slice(&[(0, 1); 10]);
7787

7888
assert_eq!(arq.query(view, 0, 9), (0, 10));
7989

@@ -97,8 +107,8 @@ mod test {
97107

98108
#[test]
99109
fn test_dynamic_supply_demand() {
100-
let mut arq = DynamicArq::<SupplyDemand>::new_with_identity(false);
101-
let view = arq.build_using_initializer(0, 9);
110+
let mut arq = DynamicArq::<SupplyDemand>::new(false);
111+
let view = arq.build_from_identity(10);
102112

103113
arq.modify(view, 1, 1, &(25, 100));
104114
arq.modify(view, 3, 3, &(100, 30));
@@ -121,9 +131,9 @@ mod test {
121131
}
122132

123133
#[test]
124-
fn test_dynslice_binary_search_rmq() {
134+
fn test_dynamic_binary_search_rmq() {
125135
let vec = vec![2, 1, 0, -1, -2, -3, -4, -5];
126-
let mut arq = DynamicArq::<AssignMin>::new_with_identity(false);
136+
let mut arq = DynamicArq::<AssignMin>::new(false);
127137
let view = arq.build_from_slice(&vec);
128138
let first_neg = dynamic_arq::first_negative(&mut arq, view);
129139

@@ -133,22 +143,4 @@ mod test {
133143
assert_eq!(first_neg, Some(3));
134144
assert_eq!(first_neg_zeros, None);
135145
}
136-
137-
#[test]
138-
fn test_dynamic_binary_search_rmq() {
139-
let initializer = Box::new(|_, r| 2 - r);
140-
let (l_bound, r_bound) = (0, 1_000_000_000_000_000_000);
141-
let mut arq = DynamicArq::<AssignMin>::new(false, initializer);
142-
let view = arq.build_using_initializer(l_bound, r_bound);
143-
let first_neg = dynamic_arq::first_negative(&mut arq, view);
144-
145-
arq.modify(view, 2, r_bound - 1, &0);
146-
let first_neg_late = dynamic_arq::first_negative(&mut arq, view);
147-
arq.modify(view, 2, r_bound, &0);
148-
let first_neg_zeros = dynamic_arq::first_negative(&mut arq, view);
149-
150-
assert_eq!(first_neg, Some(3));
151-
assert_eq!(first_neg_late, Some(r_bound));
152-
assert_eq!(first_neg_zeros, None);
153-
}
154146
}

src/range_query/specs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub trait ArqSpec {
77
// their parts. This representation is more efficient.
88
type F: Clone;
99
/// Type of monoid elements.
10-
type M;
10+
type M: Clone;
1111

1212
/// For eager updates, compose() ho be unimplemented!(). For lazy updates:
1313
/// Require for all f,g,a: apply(compose(f, g), a) = apply(f, apply(g, a))

src/range_query/static_arq.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ impl<T: ArqSpec> StaticArq<T> {
2323
/// Initializes a static balanced tree on top of the given sequence.
2424
pub fn new(init_val: &[T::M]) -> Self {
2525
let size = init_val.len();
26-
let mut val = (0..size).map(|_| T::identity()).collect::<Vec<_>>();
27-
val.extend(init_val.iter().map(|v| T::op(&T::identity(), v)));
26+
let mut val = vec![T::identity(); size];
27+
val.extend_from_slice(init_val);
2828
let app = vec![None; size];
2929

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

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