数列 - 加法セグメントツリー

i64 の和に関するセグメントツリーの定義を与える.

以下の SegmentTreeSum は直接 i64 でやり取り出来るAPIを提供しているが, 内部では Sum モノイドに包んである.

/// Sequence - Segment Tree of Sum
use crate::algebra::monoid_sum::*;
use crate::sequence::tree::segment_tree::*;

pub struct SegmentTreeSum {
    pub t: SegmentTree<Sum>,
}
impl SegmentTreeSum {
    pub fn new(size: usize) -> Self {
        let t = SegmentTree::new(size);
        Self { t }
    }
    pub fn from(xs: Vec<i128>) -> Self {
        let t = SegmentTree::from(xs.iter().map(|&x| Sum(x)).collect());
        Self { t }
    }
    pub fn to_vec(self) -> Vec<i128> {
        self.t.to_vec().iter().map(|sm| sm.0).collect()
    }
    pub fn update(&mut self, i: usize, x: i128) {
        self.t.update(i, Sum(x));
    }
    pub fn product(&self, range: std::ops::Range<usize>) -> i128 {
        self.t.product(range).0
    }
}

#[cfg(test)]
mod test_segment_tree_sum {
    use crate::sequence::tree::segment_tree_sum::*;

    #[test]
    fn test_segment_tree_sum() {
        let mut v = vec![1, 2, 3, 4];
        let mut st = SegmentTreeSum::from(v.clone());

        // assert with naiive sum
        for i in 0..v.len() {
            for j in i..v.len() {
                let mut naiive_sum = 0;
                for k in i..j {
                    naiive_sum += v[k];
                }
                assert_eq!(st.product(i..j), naiive_sum);
            }
        }

        st.update(1, -2);
        v[1] = -2;

        // assert with naiive sum
        for i in 0..v.len() {
            for j in i..v.len() {
                let mut naiive_sum = 0;
                for k in i..j {
                    naiive_sum += v[k];
                }
                assert_eq!(st.product(i..j), naiive_sum);
            }
        }
    }
}