dsalgo 0.3.10

A package for Datastructures and Algorithms.
Documentation
use crate::{
    fenwick_tree_dual_with_instance_commutative_monoid::*,
    fenwick_tree_with_instance_abelian_group_1_indexed::*,
    fenwick_tree_with_instance_commutative_monoid_1_indexed::*,
};

impl<G: AbelianGroup> From<(G, &[G::T])> for DualFenwick<G>
where
    G::T: Clone,
{
    fn from(p: (G, &[G::T])) -> Self {
        let (g, data) = p;

        let mut data = data.to_vec();

        for i in (1..data.len()).rev() {
            data[i] = g.op(g.inv(data[i - 1].clone()), data[i].clone());
        }

        Self(Fenwick::from((g, data.as_slice())))
    }
}

impl<G: AbelianGroup> DualFenwick<G>
where
    G::T: Clone,
{
    pub fn operate(
        &mut self,
        l: usize,
        r: usize,
        x: G::T,
    ) {
        assert!(l < r && r <= self.size());

        if r < self.size() {
            self.operate_ge(r, self.0.g.inv(x.clone()));
        }

        self.operate_ge(l, x);
    }

    pub fn binary_search_from<F>(
        &self,
        is_ok: F,
        l: usize,
    ) -> usize
    where
        F: Fn(&G::T) -> bool,
    {
        assert!(l <= self.size());

        let prod_lt = if l == 0 { self.0.g.e() } else { self.get(l - 1) };

        self.0.max_right_from(
            &|prod_ge: &G::T| {
                !is_ok(&self.0.g.op(prod_lt.clone(), prod_ge.clone()))
            },
            l,
        )
    }
}

#[cfg(test)]

mod tests {

    use super::*;

    #[test]

    fn test() {
        #[derive(Debug, Clone)]

        struct G;

        impl Monoid for G {
            type T = i32;

            fn e(&self) -> Self::T {
                0
            }

            fn op(
                &self,
                l: Self::T,
                r: Self::T,
            ) -> Self::T {
                l + r
            }
        }

        impl AbelianGroup for G {
            fn inv(
                &self,
                x: Self::T,
            ) -> Self::T {
                -x
            }
        }

        let a = vec![0, 1, 0, 0];

        let n = a.len();

        let mut fw = DualFenwick::from((G {}, a.as_slice()));

        for i in 0..n {
            assert_eq!(fw.get(i), a[i]);
        }

        fw.operate(2, 3, 1);

        for i in 0..n {
            assert_eq!(fw.get(i), a[i] + if i == 2 { 1 } else { 0 });
        }

        assert_eq!(fw.binary_search_from(|v| v <= &0, 1), 3);

        assert_eq!(fw.binary_search_from(|v| v <= &-1, 1), n);
    }
}