#[cfg(test)]
mod comprehensive_test_lazy_seg_tree {
use array_range_query::{LazySegTree, LazySegTreeSpec};
use rand::Rng;
#[derive(Clone, Debug, PartialEq)]
enum UpdateType {
Add(i32),
Replace(i32),
}
struct TreeSpec;
type Type = (i64, i32, i32);
impl LazySegTreeSpec for TreeSpec {
type T = Type;
const ID: Self::T = (0, i32::MAX, i32::MIN);
type U = UpdateType;
fn op_on_data(d1: &mut Self::T, d2: &Self::T) {
d1.0 += d2.0;
d1.1 = d1.1.min(d2.1);
d1.2 = d1.2.max(d2.2);
}
fn op_on_update(u1: &mut Self::U, u2: &Self::U) {
match u2 {
UpdateType::Replace(x) => *u1 = UpdateType::Replace(*x),
UpdateType::Add(x) => match u1 {
UpdateType::Replace(y) => *u1 = UpdateType::Replace(*y + *x),
UpdateType::Add(y) => *u1 = UpdateType::Add(*y + *x),
},
}
}
fn op_update_on_data(u: &Self::U, d: &mut Self::T, size: usize) {
match u {
UpdateType::Replace(x) => {
d.0 = *x as i64 * size as i64;
d.1 = *x;
d.2 = *x;
}
UpdateType::Add(x) => {
d.0 += *x as i64 * size as i64;
d.1 += *x;
d.2 += *x;
}
}
}
}
fn brute_force_query(slice: &[i32]) -> (i64, i32, i32) {
if slice.is_empty() {
return (0, i32::MAX, i32::MIN); }
let mut sum = 0i64;
let mut min = i32::MAX;
let mut max = i32::MIN;
for &x in slice {
sum += x as i64;
min = min.min(x);
max = max.max(x);
}
(sum, min, max)
}
#[test]
fn test_small_range_queries_on_sequence() {
let size = 10;
let vec: Vec<i32> = (0..size).map(|i| -200 + (i as i32 * 3)).collect();
let tree_data: Vec<Type> = vec.iter().map(|&x| (x as i64, x, x)).collect();
let tree = LazySegTree::<TreeSpec>::from_vec(tree_data);
for start in 0..=(size - 5) {
for length in 1..=5 {
let end = start + length;
let range = start..end;
println!("Querying range {:#?}", range);
let expected = brute_force_query(&vec[range.clone()]);
let result = tree.query(range.clone());
assert_eq!(
result, expected,
"Query failed for range {:#?} on initial sequence",
range
);
}
}
}
#[test]
fn test_randomized_updates_and_queries() {
let mut rng = rand::rng();
let tree_size = 500;
for trial in 0..10 {
let mut vec: Vec<i32> = (0..tree_size)
.map(|_| rng.random_range(-1000..=1000))
.collect();
let tree_data: Vec<(i64, i32, i32)> = vec.iter().map(|&x| (x as i64, x, x)).collect();
let mut tree = LazySegTree::<TreeSpec>::from_vec(tree_data);
for op in 0..100 {
let l = rng.random_range(0..tree_size);
let r = rng.random_range(l..=tree_size);
let range = l..r;
if rng.random_bool(0.5) {
println!("Querying range {:#?}...", range);
let expected = brute_force_query(&vec[range.clone()]);
let result = tree.query(range.clone());
assert_eq!(
result, expected,
"Randomized Query failed. Trial {}, Op {}. Range: {:#?}",
trial, op, range
);
} else {
let value = rng.random_range(-100..=100);
if rng.random_bool(0.5) {
println!("Adding range {:#?} with value {}", range, value);
for item in vec[range.clone()].iter_mut() {
*item += value;
}
tree.update(range.clone(), UpdateType::Add(value));
} else {
println!("Replacing range {:#?} with value {}", range, value);
for item in vec[range.clone()].iter_mut() {
*item = value;
}
tree.update(range.clone(), UpdateType::Replace(value));
}
}
}
}
}
}