dsalgo 0.3.10

A package for Datastructures and Algorithms.
Documentation
use crate::fenwick_tree_with_instance_commutative_monoid_1_indexed::*;

pub trait AbelianGroup: Monoid {
    fn inv(
        &self,
        x: Self::T,
    ) -> Self::T;
}

impl<G: AbelianGroup> Fenwick<G>
where
    G::T: Clone,
{
    pub fn fold(
        &self,
        l: usize,
        r: usize,
    ) -> G::T {
        assert!(l <= r);

        self.g.op(self.g.inv(self.fold_lt(l)), self.fold_lt(r))
    }

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

        assert!(l <= n);

        let mut i = 0;

        let mut v = self.g.inv(self.fold_lt(l));

        let mut d = (n + 1).next_power_of_two();

        loop {
            d >>= 1;

            if d == 0 {
                debug_assert!(l <= i && i <= n);

                return i;
            }

            if i + d > n {
                continue;
            }

            let nv = self.g.op(v.clone(), self.node[i + d].clone());

            if i + d <= l || is_ok(&nv) {
                i += d;

                v = nv;
            }
        }
    }

    pub fn min_left_from<F>(
        &self,
        is_ok: F,
        r: usize,
    ) -> usize
    where
        F: Fn(&G::T) -> bool,
    {
        let n = self.size();

        assert!(r <= n);

        if r == 0 {
            return 0;
        }

        let mut v = self.fold_lt(r);

        let mut d = (n + 1).next_power_of_two();

        if is_ok(&v) {
            return 0;
        }

        let mut i = 1;

        loop {
            d >>= 1;

            if d == 0 {
                debug_assert!(i <= r);

                return i;
            }

            if i + d > r {
                continue;
            }

            let nv =
                self.g.op(self.g.inv(self.node[i + d - 1].clone()), v.clone());

            if !is_ok(&nv) {
                i += d;

                v = nv;
            }
        }
    }
}

#[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 = Fenwick::from((G {}, a.as_slice()));

        assert_eq!(fw.fold(0, n), 1);

        fw.operate(2, 1);

        assert_eq!(fw.max_right_from(|v| v <= &1, 1), 2);

        assert_eq!(fw.max_right_from(|v| v <= &1, 2), n);

        assert_eq!(fw.min_left_from(|v| v <= &1, n), 2);

        assert_eq!(fw.min_left_from(|v| v <= &2, n), 0);

        assert_eq!(fw.min_left_from(|v| v <= &1, 2), 0);

        assert_eq!(fw.min_left_from(|v| v <= &0, n), 3);
    }
}