haar_lib/ds/
cumulative_sum_1d.rs1pub use crate::algebra::traits::Group;
4use std::ops::{Index, Range};
5
6#[derive(Debug, Clone)]
8pub struct CumulativeSum1D<G: Group> {
9 data: Vec<G>,
10}
11
12pub struct CumulativeSum1DBuilder<G: Group> {
14 data: Vec<G>,
15}
16
17impl<G: Group + Copy> CumulativeSum1D<G> {
18 pub fn fold(&self, Range { start: l, end: r }: Range<usize>) -> G {
20 self.data[r].op(self.data[l].inv())
21 }
22}
23
24impl<G: Group> Index<usize> for CumulativeSum1D<G> {
25 type Output = G;
26
27 fn index(&self, i: usize) -> &Self::Output {
28 &self.data[i]
29 }
30}
31
32impl<G: Group + Copy> CumulativeSum1DBuilder<G> {
33 pub fn new(n: usize) -> Self {
35 CumulativeSum1DBuilder {
36 data: vec![G::id(); n + 1],
37 }
38 }
39
40 pub fn assign(&mut self, i: usize, value: G) {
42 self.data[i + 1] = value;
43 }
44
45 pub fn update(&mut self, i: usize, value: G) {
47 self.data[i + 1] = self.data[i + 1].op(value);
48 }
49
50 pub fn build(self) -> CumulativeSum1D<G> {
52 let data = self
53 .data
54 .iter()
55 .scan(G::id(), |st, &x| {
56 *st = st.op(x);
57 Some(*st)
58 })
59 .collect::<Vec<_>>();
60
61 CumulativeSum1D { data }
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::algebra::sum::*;
69 use my_testtools::*;
70 use rand::Rng;
71
72 #[test]
73 fn test() {
74 let mut rng = rand::thread_rng();
75
76 let n = 20;
77 let mut csb = CumulativeSum1DBuilder::<Sum<i32>>::new(n);
78
79 let mut other = vec![Sum::id(); n];
80
81 for _ in 0..1000 {
82 let i = rng.gen_range(0..n);
83 let x = rng.gen_range(-1000..=1000);
84
85 csb.update(i, Sum(x));
86 other[i].op_assign_r(Sum(x));
87 }
88
89 let cs = csb.build();
90
91 for _ in 0..100 {
92 let range = rand_range(&mut rng, 0..n);
93 let ans = other[range.clone()].iter().cloned().fold_m();
94 assert_eq!(cs.fold(range), ans);
95 }
96 }
97}