segment_tree/
propagating.rs

1use std::mem;
2use std::default::Default;
3
4use crate::ops::{Commutative, Identity};
5
6/// This data structure allows range modification and single element queries.
7///
8/// This tree allocates `2n * sizeof(N)` bytes of memory.
9///
10/// This tree is implemented using a binary tree, where each node contains the changes
11/// that need to be propogated to its children.
12///
13/// # Examples
14///
15/// Quickly add something to every value in some interval.
16///
17/// ```rust
18/// use segment_tree::PointSegment;
19/// use segment_tree::ops::Add;
20///
21/// use std::iter::repeat;
22///
23/// // make a giant tree of zeroes
24/// let mut tree = PointSegment::build(repeat(0).take(1_000_000).collect(), Add);
25///
26/// // add one to every value between 200 and 500000
27/// tree.modify(200, 500_000, 1);
28/// assert_eq!(tree.query(100), 0);
29/// assert_eq!(tree.query(200), 1);
30/// assert_eq!(tree.query(500), 1);
31/// assert_eq!(tree.query(499_999), 1);
32/// assert_eq!(tree.query(500_000), 0);
33///
34/// // add five to every value between 0 and 1000
35/// tree.modify(0, 1000, 5);
36/// assert_eq!(tree.query(10), 5);
37/// assert_eq!(tree.query(500), 6);
38/// assert_eq!(tree.query(10_000), 1);
39/// assert_eq!(tree.query(600_000), 0);
40/// ```
41pub struct PointSegment<N, O> where O: Commutative<N> + Identity<N> {
42    buf: Vec<N>,
43    n: usize,
44    op: O
45}
46
47impl<N, O: Commutative<N> + Identity<N>> PointSegment<N, O> {
48    /// Builds a tree using the given buffer. If the given buffer is less than half full,
49    /// this function allocates.
50    /// Uses `O(len)` time.
51    pub fn build(mut buf: Vec<N>, op: O) -> PointSegment<N, O> {
52        let n = buf.len();
53        buf.reserve_exact(n);
54        for i in 0..n {
55            let val = mem::replace(&mut buf[i], op.identity());
56            buf.push(val);
57        }
58        PointSegment { buf: buf, n: n, op: op }
59    }
60    /// Allocate a new buffer and build the tree using the values in the slice.
61    /// Uses `O(len)` time.
62    pub fn build_slice(buf: &[N], op: O) -> PointSegment<N, O> where N: Clone {
63        PointSegment::build_iter(buf.iter().cloned(), op)
64    }
65    /// Allocate a new buffer and build the tree using the values in the iterator.
66    /// Uses `O(len)` time.
67    pub fn build_iter<I: ExactSizeIterator<Item=N>>(iter: I, op: O) -> PointSegment<N, O> {
68        let n = iter.len();
69        let mut buf = Vec::with_capacity(2*n);
70        for _ in 0..n { buf.push(op.identity()); }
71        buf.extend(iter);
72        PointSegment {
73            buf: buf,
74            n: n, op: op
75        }
76    }
77    /// Computes the value at `p`.
78    /// Uses `O(log(len))` time.
79    pub fn query(&self, mut p: usize) -> N {
80        p += self.n;
81        let mut res = self.op.identity();
82        while p > 0 {
83            res = self.op.combine_left(res, &self.buf[p]);
84            p >>= 1;
85        }
86        res
87    }
88    /// Combine every value in the interval with `delta`.
89    /// Uses `O(log(len))` time.
90    pub fn modify(&mut self, mut l: usize, mut r: usize, delta: N) {
91        l += self.n; r += self.n;
92        while l < r {
93            if l&1 == 1 {
94                self.op.combine_mut(&mut self.buf[l], &delta);
95                l += 1;
96            }
97            if r&1 == 1 {
98                r -= 1;
99                self.op.combine_mut(&mut self.buf[r], &delta);
100            }
101            l >>= 1; r >>= 1;
102        }
103    }
104    /// Propogate all changes to the leaves in the tree and return a mutable slice
105    /// containing the leaves.
106    ///
107    /// Uses `O(len)` time.
108    pub fn propogate(&mut self) -> &mut [N] {
109        for i in 1..self.n {
110            let prev = mem::replace(&mut self.buf[i], self.op.identity());
111            self.op.combine_mut(&mut self.buf[i<<1], &prev);
112            self.op.combine_mut(&mut self.buf[i<<1|1], &prev);
113        }
114        &mut self.buf[self.n..]
115    }
116    /// Returns the number of values in the underlying array.
117    /// Uses `O(1)` time.
118    #[inline(always)]
119    pub fn len(&self) -> usize {
120        self.n
121    }
122}
123
124impl<N: Clone, O: Identity<N> + Commutative<N> + Clone> Clone for PointSegment<N, O> {
125    #[inline]
126    fn clone(&self) -> PointSegment<N, O> {
127        PointSegment {
128            buf: self.buf.clone(), n: self.n, op: self.op.clone()
129        }
130    }
131}
132impl<N, O: Identity<N> + Commutative<N> + Default> Default for PointSegment<N, O> {
133    #[inline]
134    fn default() -> PointSegment<N, O> {
135        PointSegment { buf: Vec::new(), n: 0, op: Default::default() }
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use crate::propagating::*;
142    use crate::ops::*;
143    use rand::prelude::*;
144    use rand::distributions::Standard;
145    use std::num::Wrapping;
146
147    #[test]
148    fn test() {
149        let mut rng = thread_rng();
150        for i in 1..130 {
151            let mut buf: Vec<Wrapping<i32>> = rng.sample_iter(&Standard)
152                .map(|n| Wrapping(n)).take(i).collect();
153            let mut tree = match i%3 {
154                0 => PointSegment::build_slice(&buf[..], Add),
155                1 => PointSegment::build_iter(buf.iter().cloned(), Add),
156                2 => PointSegment::build(buf.clone(), Add),
157                _ => unreachable!()
158            };
159            let tests: Vec<(usize, usize, i32)> = rng.sample_iter(&Standard)
160                .take(10).collect();
161            for (n, m, v) in tests {
162                let n = n % i;
163                let m = m % i;
164                if n > m { continue; }
165                for index in n..m { buf[index] += Wrapping(v); }
166                tree.modify(n, m, Wrapping(v));
167                for index in 0..i {
168                    assert_eq!(buf[index], tree.query(index));
169                }
170            }
171            assert_eq!(&mut buf[..], tree.propogate());
172        }
173    }
174}