forked from EbTech/rust-algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharq_tree.rs
More file actions
220 lines (199 loc) · 6.44 KB
/
Copy patharq_tree.rs
File metadata and controls
220 lines (199 loc) · 6.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//! Associative Range Query Tree based on [Al.Cash's compact representation]
//! (http://codeforces.com/blog/entry/18051).
/// Colloquially known as a "segtree" in the sport programming literature, it
/// represents a sequence of elements a_i (0 <= i < size) from a monoid (M, +)
/// on which we want to support fast range operations:
///
/// - modify(l, r, f) replaces a_i (l <= i <= r) by f(a_i) for an endomorphism f
/// - query(l, r) returns the aggregate a_l + a_{l+1} + ... + a_r
pub struct ArqTree<T: ArqSpec> {
d: Vec<Option<T::F>>,
t: Vec<T::M>,
}
impl<T: ArqSpec> ArqTree<T>
where
T::F: Clone,
{
/// Initializes a static balanced tree on top of the given sequence.
pub fn new(mut init: Vec<T::M>) -> Self {
let size = init.len();
let mut t = (0..size).map(|_| T::identity()).collect::<Vec<_>>();
t.append(&mut init);
for i in (0..size).rev() {
t[i] = T::op(&t[i << 1], &t[i << 1 | 1]);
}
Self {
d: vec![None; size],
t,
}
}
fn apply(&mut self, p: usize, f: &T::F) {
self.t[p] = T::apply(f, &self.t[p]);
if p < self.d.len() {
let h = match self.d[p] {
Some(ref g) => T::compose(f, g),
None => f.clone(),
};
self.d[p] = Some(h);
}
}
fn push(&mut self, p: usize) {
for s in (1..32).rev() {
let i = p >> s;
if let Some(ref f) = self.d[i].take() {
self.apply(i << 1, f);
self.apply(i << 1 | 1, f);
}
}
}
fn pull(&mut self, mut p: usize) {
while p > 1 {
p >>= 1;
if self.d[p].is_none() {
self.t[p] = T::op(&self.t[p << 1], &self.t[p << 1 | 1]);
}
}
}
/// Applies the endomorphism f to all entries from l to r, inclusive.
///
/// # Panics
///
/// Panics if l or r is out of range.
pub fn modify(&mut self, mut l: usize, mut r: usize, f: &T::F) {
l += self.d.len();
r += self.d.len();
let (l0, r0) = (l, r);
self.push(l0);
self.push(r0);
while l <= r {
if l & 1 == 1 {
self.apply(l, f);
l += 1;
}
if r & 1 == 0 {
self.apply(r, f);
r -= 1;
}
l >>= 1;
r >>= 1;
}
self.pull(l0);
self.pull(r0);
}
/// Returns the aggregate range query on all entries from l to r, inclusive.
///
/// # Panics
///
/// Panics if l or r is out of range.
pub fn query(&mut self, mut l: usize, mut r: usize) -> T::M {
l += self.d.len();
r += self.d.len();
self.push(l);
self.push(r);
let (mut l_agg, mut r_agg) = (T::identity(), T::identity());
while l <= r {
if l & 1 == 1 {
l_agg = T::op(&l_agg, &self.t[l]);
l += 1;
}
if r & 1 == 0 {
r_agg = T::op(&self.t[r], &r_agg);
r -= 1;
}
l >>= 1;
r >>= 1;
}
T::op(&l_agg, &r_agg)
}
}
pub trait ArqSpec {
/// Type of data representing an endomorphism.
// Note that while a Fn(M) -> M may seem like a more natural representation
// for an endomorphism, compositions would then have to delegate to each of
// their parts. This representation is more efficient.
type F;
/// Type of monoid elements.
type M;
/// Require for all f,g,a: apply(compose(f, g), a) = apply(f, apply(g, a))
fn compose(f: &Self::F, g: &Self::F) -> Self::F;
/// Require for all f,a,b: apply(f, op(a, b)) = op(apply(f, a), apply(f, b))
fn apply(f: &Self::F, a: &Self::M) -> Self::M;
/// Require for all a,b,c: op(a, op(b, c)) = op(op(a, b), c)
fn op(a: &Self::M, b: &Self::M) -> Self::M;
/// Require for all a: op(a, identity()) = op(identity(), a) = a
fn identity() -> Self::M;
}
/// Range Minimum Query, a classic application of associative range query.
// Exercises: try augmenting this struct to find the index of a minimum element
// in a range query, as well as the number of elements that match the minimum.
// Then instead of assigning to a range, try to support the operation of
// incrementing each element in a range by a given offset!
pub struct AssignMin;
impl ArqSpec for AssignMin {
type F = i64;
type M = i64;
fn compose(f: &Self::F, _: &Self::F) -> Self::F {
*f
}
fn apply(f: &Self::F, _: &Self::M) -> Self::M {
*f
}
fn op(a: &Self::M, b: &Self::M) -> Self::M {
(*a).min(*b)
}
fn identity() -> Self::M {
Self::M::max_value()
}
}
/// A slightly more advanced application, where we aim to support range sum
/// queries and range constant assignments.
/// Note that constant assignment f_c(a) = c is not a endomorphism on (i64, +)
/// because f_c(a+b) = c != 2*c = f_c(a) + f_c(b). In intuitive terms, the
/// problem is that the internal nodes of the tree should not simply be set to
/// c, but rather, to c multiplied by the subtree size. So let's augment the
/// monoid type with size information, using the 2D vector (a_i,1) instead of
/// a_i. Now check that f_c((a, s)) = (c*s, s) is indeed an endomorphism on
/// vector addition: f_c((a,s)+(b,t)) = f_c((a+b,s+t)) = (c*(s+t),s+t)
/// = (c*s,s)+(c*t,t) = f_c((a,s)) + f_c((b,t)).
///
/// # Panics
///
/// Associated functions will panic on overflow.
pub struct AssignSum;
impl ArqSpec for AssignSum {
type F = i64;
type M = (i64, i64);
fn compose(f: &Self::F, _: &Self::F) -> Self::F {
*f
}
fn apply(f: &Self::F, a: &Self::M) -> Self::M {
(f * a.1, a.1)
}
fn op(a: &Self::M, b: &Self::M) -> Self::M {
(a.0 + b.0, a.1 + b.1)
}
fn identity() -> Self::M {
(0, 0)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_range_sum() {
let mut arq = ArqTree::<AssignSum>::new(vec![(0, 1); 10]);
assert_eq!(arq.query(0, 9), (0, 10));
arq.modify(1, 3, &10);
arq.modify(3, 5, &1);
assert_eq!(arq.query(0, 9), (23, 10));
}
#[test]
fn test_rmq() {
let mut arq = ArqTree::<AssignMin>::new(vec![0; 10]);
assert_eq!(arq.query(0, 9), 0);
arq.modify(2, 4, &-5);
arq.modify(5, 7, &-3);
arq.modify(1, 6, &1);
assert_eq!(arq.query(0, 9), -3);
}
}