#[derive(Debug, Clone)]
pub struct SegmentTree {
    data: Vec<i64>,
    mode: Mode,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Mode {
    RangeUpdate(Op),
    RangeGet(Op),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Op {
    Max,
    Min,
    Add,
}
impl SegmentTree {
    const SEQ_LEN: usize = 1 << 20;
    const MAX: i64 = 1_000_000_000_000;
    const MIN: i64 = -1_000_000_000_000;
    pub fn new(mode: Mode) -> Self {
        let default = match &mode {
            Mode::RangeGet(op) => SegmentTree::default(op),
            Mode::RangeUpdate(op) => SegmentTree::default(op),
        };
        Self {
            data: vec![default; 2 * SegmentTree::SEQ_LEN],
            mode,
        }
    }
    pub fn default(op: &Op) -> i64 {
        match op {
            Op::Add => 0,
            Op::Max => SegmentTree::MIN,
            Op::Min => SegmentTree::MAX,
        }
    }
    pub fn get_one(&mut self, mut index: usize) -> i64 {
        index += SegmentTree::SEQ_LEN;
        let mut ret = 0;
        if let Mode::RangeUpdate(op) = &self.mode {
            let operator = match op {
                Op::Add => |ret: &mut i64, v: i64| *ret += v,
                _ => panic!(),
            };
            operator(&mut ret, self.data[index]);
            while index > 0 {
                index /= 2;
                operator(&mut ret, self.data[index]);
            }
        } else {
            panic!("Unsupported");
        }
        ret
    }
    fn range_query_recursive(
        &self,
        op: &Op,
        ql: usize,
        qr: usize,
        sl: usize,
        sr: usize,
        pos: usize,
    ) -> i64 {
        if qr <= sl || sr <= ql {
            return SegmentTree::default(op);
        }
        if ql <= sl && sr <= qr {
            return self.data[pos];
        }
        fn add(l: i64, r: i64) -> i64 {
            l + r
        }
        fn max(l: i64, r: i64) -> i64 {
            l.max(r)
        }
        fn min(l: i64, r: i64) -> i64 {
            l.min(r)
        }
        let sm = (sl + sr) / 2;
        let lv = self.range_query_recursive(op, ql, qr, sl, sm, pos * 2);
        let rv = self.range_query_recursive(op, ql, qr, sm, sr, pos * 2 + 1);
        let operate = match op {
            Op::Add => add,
            Op::Max => max,
            Op::Min => min,
        };
        operate(lv, rv)
    }
    pub fn get_range(&self, l: usize, r: usize) -> i64 {
        if let Mode::RangeGet(op) = &self.mode {
            self.range_query_recursive(op, l, r, 0, SegmentTree::SEQ_LEN, 1)
        } else {
            panic!("Unsupported");
        }
    }
    pub fn update_one(&mut self, mut index: usize, value: i64) {
        index += SegmentTree::SEQ_LEN;
        fn add_assign_one(ret: &mut i64, v: i64) {
            *ret += v;
        }
        fn max_assign_one(ret: &mut i64, v: i64) {
            *ret = v;
        }
        fn min_assign_one(ret: &mut i64, v: i64) {
            *ret = v;
        }
        fn add_assign(ret: &mut i64, l: i64, r: i64) {
            *ret = l + r;
        }
        fn max_assign(ret: &mut i64, l: i64, r: i64) {
            *ret = l.max(r);
        }
        fn min_assign(ret: &mut i64, l: i64, r: i64) {
            *ret = l.min(r);
        }
        if let Mode::RangeGet(op) = &self.mode {
            let operate_and_assign_one = match op {
                Op::Add => add_assign_one,
                Op::Max => max_assign_one,
                Op::Min => min_assign_one,
            };
            operate_and_assign_one(&mut self.data[index], value);
            let operate_and_assign = match op {
                Op::Add => add_assign,
                Op::Max => max_assign,
                Op::Min => min_assign,
            };
            while index > 0 {
                index /= 2;
                let lv = self.data[index * 2];
                let rv = self.data[index * 2 + 1];
                operate_and_assign(&mut self.data[index], lv, rv);
            }
        }
    }
    pub fn update_range(&mut self, mut l: usize, mut r: usize, value: i64) {
        if let Mode::RangeUpdate(op) = &self.mode {
            let operate_and_assign_one = match op {
                Op::Add => |ret: &mut i64, v: i64| *ret += v,
                _ => panic!(),
            };
            l += SegmentTree::SEQ_LEN;
            r += SegmentTree::SEQ_LEN;
            while l < r {
                if l % 2 == 1 {
                    operate_and_assign_one(&mut self.data[l], value);
                    l += 1;
                }
                l /= 2;
                if r % 2 == 1 {
                    operate_and_assign_one(&mut self.data[r - 1], value);
                    r -= 1;
                }
                r /= 2;
            }
        } else {
            panic!("Unsupported");
        }
    }
}
#[cfg(test)]
mod test_segment_tree {
    use crate::tree::segment_tree::Mode;
    use crate::tree::segment_tree::Op;
    use crate::tree::segment_tree::SegmentTree;
    #[test]
    fn it_works_raq() {
        let mut raq = SegmentTree::new(Mode::RangeUpdate(Op::Add));
        raq.update_range(1, 2, 1);
        raq.update_range(2, 4, 2);
        raq.update_range(3, 4, 3);
        assert_eq!(raq.get_one(0), 0);
        assert_eq!(raq.get_one(2), 2);
        assert_eq!(raq.get_one(3), 5);
    }
    #[test]
    fn it_works_rsq() {
        let mut rsq = SegmentTree::new(Mode::RangeGet(Op::Add));
        rsq.update_one(0, 3);
        rsq.update_one(2, 3);
        rsq.update_one(3, 1);
        rsq.update_one(4, 4);
        assert_eq!(rsq.get_range(0, 3), 6);
        assert_eq!(rsq.get_range(1, 3), 3);
        assert_eq!(rsq.get_range(2, 4), 4);
        assert_eq!(rsq.get_range(3, 4), 1);
        assert_eq!(rsq.get_range(1, 6), 8);
        assert_eq!(rsq.get_range(0, 0), 0);
    }
    #[test]
    fn it_works_rmaxq() {
        let mut rmaxq = SegmentTree::new(Mode::RangeGet(Op::Max));
        rmaxq.update_one(0, 10);
        rmaxq.update_one(2, 101);
        rmaxq.update_one(100, 1001);
        assert_eq!(rmaxq.get_range(0, 1), 10);
        assert_eq!(rmaxq.get_range(0, 2), 10);
        assert_eq!(rmaxq.get_range(0, 3), 101);
        assert_eq!(rmaxq.get_range(0, 100100), 1001);
        assert_eq!(rmaxq.get_range(101, 1000), SegmentTree::MIN);
        assert_eq!(rmaxq.get_range(0, 0), SegmentTree::MIN);
    }
    #[test]
    fn it_works_rminq() {
        let mut rminq = SegmentTree::new(Mode::RangeGet(Op::Min));
        rminq.update_one(0, 101);
        rminq.update_one(2, 10);
        rminq.update_one(100, 1001);
        assert_eq!(rminq.get_range(0, 1), 101);
        assert_eq!(rminq.get_range(0, 2), 101);
        assert_eq!(rminq.get_range(0, 3), 10);
        assert_eq!(rminq.get_range(0, 100100), 10);
        assert_eq!(rminq.get_range(101, 1000), SegmentTree::MAX);
        assert_eq!(rminq.get_range(0, 0), SegmentTree::MAX);
    }
}