Skip to content

Commit 6dc1d98

Browse files
authored
Add Lazy Segment Tree (TheAlgorithms#501)
1 parent 0d40c84 commit 6dc1d98

File tree

2 files changed

+273
-0
lines changed

2 files changed

+273
-0
lines changed
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
use std::fmt::{Debug, Display};
2+
use std::ops::Add;
3+
use std::ops::AddAssign;
4+
use std::ops::Range;
5+
6+
pub struct LazySegmentTree<T: Debug + Default + Ord + Copy + Display + AddAssign + Add<Output = T>>
7+
{
8+
len: usize,
9+
tree: Vec<T>,
10+
lazy: Vec<Option<T>>,
11+
merge: fn(T, T) -> T,
12+
}
13+
14+
impl<T: Debug + Default + Ord + Copy + Display + AddAssign + Add<Output = T>> LazySegmentTree<T> {
15+
pub fn from_vec(arr: &[T], merge: fn(T, T) -> T) -> Self {
16+
let len = arr.len();
17+
let mut sgtr = LazySegmentTree {
18+
len,
19+
tree: vec![T::default(); 4 * len],
20+
lazy: vec![None; 4 * len],
21+
merge,
22+
};
23+
if len != 0 {
24+
sgtr.build_recursive(arr, 1, 0..len, merge);
25+
}
26+
sgtr
27+
}
28+
29+
fn build_recursive(
30+
&mut self,
31+
arr: &[T],
32+
idx: usize,
33+
range: Range<usize>,
34+
merge: fn(T, T) -> T,
35+
) {
36+
if range.end - range.start == 1 {
37+
self.tree[idx] = arr[range.start];
38+
} else {
39+
let mid = (range.start + range.end) / 2;
40+
self.build_recursive(arr, 2 * idx, range.start..mid, merge);
41+
self.build_recursive(arr, 2 * idx + 1, mid..range.end, merge);
42+
self.tree[idx] = merge(self.tree[2 * idx], self.tree[2 * idx + 1]);
43+
}
44+
}
45+
46+
pub fn query(&mut self, range: Range<usize>) -> Option<T> {
47+
self.query_recursive(1, 0..self.len, &range)
48+
}
49+
50+
fn query_recursive(
51+
&mut self,
52+
idx: usize,
53+
element_range: Range<usize>,
54+
query_range: &Range<usize>,
55+
) -> Option<T> {
56+
if element_range.start >= query_range.end || element_range.end <= query_range.start {
57+
return None;
58+
}
59+
if self.lazy[idx].is_some() {
60+
self.propagation(idx, &element_range, T::default());
61+
}
62+
if element_range.start >= query_range.start && element_range.end <= query_range.end {
63+
return Some(self.tree[idx]);
64+
}
65+
let mid = (element_range.start + element_range.end) / 2;
66+
let left = self.query_recursive(idx * 2, element_range.start..mid, query_range);
67+
let right = self.query_recursive(idx * 2 + 1, mid..element_range.end, query_range);
68+
match (left, right) {
69+
(None, None) => None,
70+
(None, Some(r)) => Some(r),
71+
(Some(l), None) => Some(l),
72+
(Some(l), Some(r)) => Some((self.merge)(l, r)),
73+
}
74+
}
75+
76+
pub fn update(&mut self, target_range: Range<usize>, val: T) {
77+
self.update_recursive(1, 0..self.len, &target_range, val);
78+
}
79+
80+
fn update_recursive(
81+
&mut self,
82+
idx: usize,
83+
element_range: Range<usize>,
84+
target_range: &Range<usize>,
85+
val: T,
86+
) {
87+
if element_range.start >= target_range.end || element_range.end <= target_range.start {
88+
return;
89+
}
90+
if element_range.end - element_range.start == 1 {
91+
self.tree[idx] += val;
92+
return;
93+
}
94+
if element_range.start >= target_range.start && element_range.end <= target_range.end {
95+
self.lazy[idx] = match self.lazy[idx] {
96+
Some(lazy) => Some(lazy + val),
97+
None => Some(val),
98+
};
99+
return;
100+
}
101+
if self.lazy[idx].is_some() && self.lazy[idx].unwrap() != T::default() {
102+
self.propagation(idx, &element_range, T::default());
103+
}
104+
let mid = (element_range.start + element_range.end) / 2;
105+
self.update_recursive(idx * 2, element_range.start..mid, target_range, val);
106+
self.update_recursive(idx * 2 + 1, mid..element_range.end, target_range, val);
107+
self.tree[idx] = (self.merge)(self.tree[idx * 2], self.tree[idx * 2 + 1]);
108+
self.lazy[idx] = Some(T::default());
109+
}
110+
111+
fn propagation(&mut self, idx: usize, element_range: &Range<usize>, parent_lazy: T) {
112+
if element_range.end - element_range.start == 1 {
113+
self.tree[idx] += parent_lazy;
114+
return;
115+
}
116+
117+
let lazy = self.lazy[idx].unwrap_or(T::default());
118+
self.lazy[idx] = None;
119+
120+
let mid = (element_range.start + element_range.end) / 2;
121+
self.propagation(idx * 2, &(element_range.start..mid), parent_lazy + lazy);
122+
self.propagation(idx * 2 + 1, &(mid..element_range.end), parent_lazy + lazy);
123+
self.tree[idx] = (self.merge)(self.tree[idx * 2], self.tree[idx * 2 + 1]);
124+
}
125+
}
126+
127+
#[cfg(test)]
128+
mod tests {
129+
use super::*;
130+
use quickcheck::TestResult;
131+
use quickcheck_macros::quickcheck;
132+
use std::cmp::{max, min};
133+
134+
#[test]
135+
fn test_min_segments() {
136+
let vec = vec![-30, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8];
137+
let mut min_seg_tree = LazySegmentTree::from_vec(&vec, min);
138+
// [-30, 2, -4, 7, (3, -5, 6), 11, -20, 9, 14, 15, 5, 2, -8]
139+
assert_eq!(Some(-5), min_seg_tree.query(4..7));
140+
// [(-30, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8)]
141+
assert_eq!(Some(-30), min_seg_tree.query(0..vec.len()));
142+
// [(-30, 2), -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
143+
assert_eq!(Some(-30), min_seg_tree.query(0..2));
144+
// [-30, (2, -4), 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
145+
assert_eq!(Some(-4), min_seg_tree.query(1..3));
146+
// [-30, (2, -4, 7, 3, -5, 6), 11, -20, 9, 14, 15, 5, 2, -8]
147+
assert_eq!(Some(-5), min_seg_tree.query(1..7));
148+
}
149+
150+
#[test]
151+
fn test_max_segments() {
152+
let vec = vec![-30, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8];
153+
let mut max_seg_tree = LazySegmentTree::from_vec(&vec, max);
154+
// [-30, 2, -4, 7, (3, -5, 6), 11, -20, 9, 14, 15, 5, 2, -8]
155+
assert_eq!(Some(6), max_seg_tree.query(4..7));
156+
// [(-30, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8)]
157+
assert_eq!(Some(15), max_seg_tree.query(0..vec.len()));
158+
// [(-30, 2), -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
159+
assert_eq!(Some(2), max_seg_tree.query(0..2));
160+
// [-30, (2, -4), 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
161+
assert_eq!(Some(2), max_seg_tree.query(1..3));
162+
// [-30, (2, -4, 7, 3, -5, 6), 11, -20, 9, 14, 15, 5, 2, -8]
163+
assert_eq!(Some(7), max_seg_tree.query(1..7));
164+
}
165+
166+
#[test]
167+
fn test_sum_segments() {
168+
let vec = vec![-30, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8];
169+
let mut max_seg_tree = LazySegmentTree::from_vec(&vec, |x, y| x + y);
170+
// [-30, 2, -4, 7, (3, -5, 6), 11, -20, 9, 14, 15, 5, 2, -8]
171+
assert_eq!(Some(4), max_seg_tree.query(4..7));
172+
// [(-30, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8)]
173+
assert_eq!(Some(7), max_seg_tree.query(0..vec.len()));
174+
// [(-30, 2), -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
175+
assert_eq!(Some(-28), max_seg_tree.query(0..2));
176+
// [-30, (2, -4), 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
177+
assert_eq!(Some(-2), max_seg_tree.query(1..3));
178+
// [-30, (2, -4, 7, 3, -5, 6), 11, -20, 9, 14, 15, 5, 2, -8]
179+
assert_eq!(Some(9), max_seg_tree.query(1..7));
180+
}
181+
182+
#[test]
183+
fn test_update_segments_tiny() {
184+
let vec = vec![0, 0, 0, 0, 0];
185+
let mut update_seg_tree = LazySegmentTree::from_vec(&vec, |x, y| x + y);
186+
update_seg_tree.update(0..3, 3);
187+
update_seg_tree.update(2..5, 3);
188+
assert_eq!(Some(3), update_seg_tree.query(0..1));
189+
assert_eq!(Some(3), update_seg_tree.query(1..2));
190+
assert_eq!(Some(6), update_seg_tree.query(2..3));
191+
assert_eq!(Some(3), update_seg_tree.query(3..4));
192+
assert_eq!(Some(3), update_seg_tree.query(4..5));
193+
}
194+
195+
#[test]
196+
fn test_update_segments() {
197+
let vec = vec![-30, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8];
198+
let mut update_seg_tree = LazySegmentTree::from_vec(&vec, |x, y| x + y);
199+
// -> [-30, (5, -1, 10, 6), -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
200+
update_seg_tree.update(1..5, 3);
201+
202+
// [-30, 5, -1, 10, (6 -5, 6), 11, -20, 9, 14, 15, 5, 2, -8]
203+
assert_eq!(Some(7), update_seg_tree.query(4..7));
204+
// [(-30, 5, -1, 10, 6 , -5, 6, 11, -20, 9, 14, 15, 5, 2, -8)]
205+
assert_eq!(Some(19), update_seg_tree.query(0..vec.len()));
206+
// [(-30, 5), -1, 10, 6, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
207+
assert_eq!(Some(-25), update_seg_tree.query(0..2));
208+
// [-30, (5, -1), 10, 6, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8]
209+
assert_eq!(Some(4), update_seg_tree.query(1..3));
210+
// [-30, (5, -1, 10, 6, -5, 6), 11, -20, 9, 14, 15, 5, 2, -8]
211+
assert_eq!(Some(21), update_seg_tree.query(1..7));
212+
}
213+
214+
// Some properties over segment trees:
215+
// When asking for the range of the overall array, return the same as iter().min() or iter().max(), etc.
216+
// When asking for an interval containing a single value, return this value, no matter the merge function
217+
218+
#[quickcheck]
219+
fn check_overall_interval_min(array: Vec<i32>) -> TestResult {
220+
let mut seg_tree = LazySegmentTree::from_vec(&array, min);
221+
TestResult::from_bool(array.iter().min().copied() == seg_tree.query(0..array.len()))
222+
}
223+
224+
#[quickcheck]
225+
fn check_overall_interval_max(array: Vec<i32>) -> TestResult {
226+
let mut seg_tree = LazySegmentTree::from_vec(&array, max);
227+
TestResult::from_bool(array.iter().max().copied() == seg_tree.query(0..array.len()))
228+
}
229+
230+
#[quickcheck]
231+
fn check_overall_interval_sum(array: Vec<i32>) -> TestResult {
232+
let mut seg_tree = LazySegmentTree::from_vec(&array, max);
233+
TestResult::from_bool(array.iter().max().copied() == seg_tree.query(0..array.len()))
234+
}
235+
236+
#[quickcheck]
237+
fn check_single_interval_min(array: Vec<i32>) -> TestResult {
238+
let mut seg_tree = LazySegmentTree::from_vec(&array, min);
239+
for (i, value) in array.into_iter().enumerate() {
240+
let res = seg_tree.query(i..(i + 1));
241+
if res != Some(value) {
242+
return TestResult::error(format!("Expected {:?}, got {:?}", Some(value), res));
243+
}
244+
}
245+
TestResult::passed()
246+
}
247+
248+
#[quickcheck]
249+
fn check_single_interval_max(array: Vec<i32>) -> TestResult {
250+
let mut seg_tree = LazySegmentTree::from_vec(&array, max);
251+
for (i, value) in array.into_iter().enumerate() {
252+
let res = seg_tree.query(i..(i + 1));
253+
if res != Some(value) {
254+
return TestResult::error(format!("Expected {:?}, got {:?}", Some(value), res));
255+
}
256+
}
257+
TestResult::passed()
258+
}
259+
260+
#[quickcheck]
261+
fn check_single_interval_sum(array: Vec<i32>) -> TestResult {
262+
let mut seg_tree = LazySegmentTree::from_vec(&array, max);
263+
for (i, value) in array.into_iter().enumerate() {
264+
let res = seg_tree.query(i..(i + 1));
265+
if res != Some(value) {
266+
return TestResult::error(format!("Expected {:?}, got {:?}", Some(value), res));
267+
}
268+
}
269+
TestResult::passed()
270+
}
271+
}

src/data_structures/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod binary_search_tree;
44
mod fenwick_tree;
55
mod graph;
66
mod heap;
7+
mod lazy_segment_tree;
78
mod linked_list;
89
pub mod probabilistic;
910
mod queue;
@@ -22,6 +23,7 @@ pub use self::fenwick_tree::FenwickTree;
2223
pub use self::graph::DirectedGraph;
2324
pub use self::graph::UndirectedGraph;
2425
pub use self::heap::Heap;
26+
pub use self::lazy_segment_tree::LazySegmentTree;
2527
pub use self::linked_list::LinkedList;
2628
pub use self::queue::Queue;
2729
pub use self::rb_tree::RBTree;

0 commit comments

Comments
 (0)