pub trait Magma: Sized + Clone { fn op(&self, rhs: &Self) -> Self; } pub trait Associative: Magma {} pub trait Unital: Magma { fn identity() -> Self; } pub trait Monoid: Magma + Associative + Unital {} impl Monoid for T {} pub trait Effector: Monoid { type Target; fn effect(&self, t: &Self::Target, sz: usize) -> Self::Target; } pub struct LazySegmentTree> { node: Vec, lazy: Vec, sz: usize, } impl> LazySegmentTree { pub fn init(vec: Vec) -> Self { let mut sz = 1; while sz < vec.len() { sz *= 2 } let mut node = vec![T::identity(); sz << 1]; let lazy = vec![E::identity(); sz << 1]; for i in 0..vec.len() { node[i + sz] = vec[i].clone(); } for i in (1..sz).rev() { node[i] = node[i << 1].op(&node[(i << 1) + 1]); } Self { node: node, lazy: lazy, sz: sz } } fn push(&mut self, i: usize, sz: usize) { self.node[i] = self.lazy[i].effect(&self.node[i], sz); if (i << 1) < self.node.len() { self.lazy[i << 1] = self.lazy[i << 1].op(&self.lazy[i]); self.lazy[(i << 1) + 1] = self.lazy[(i << 1) + 1].op(&self.lazy[i]); } self.lazy[i] = E::identity(); } fn update_raw(&mut self, i: usize, a: usize, b: usize, l: usize, r: usize, e: &E) { self.push(i, r - l); if b <= l || r <= a { return; } else if a <= l && r <= b { self.lazy[i] = self.lazy[i].op(e); self.push(i, r - l); } else { self.update_raw(i << 1, a, b, l, (l + r) >> 1, e); self.update_raw((i << 1) + 1, a, b, (l + r) >> 1, r, e); self.node[i] = self.node[i << 1].op(&self.node[(i << 1) + 1]); } } pub fn update_range(&mut self, l: usize, r: usize, e: E) { let sz = self.sz; self.update_raw(1, l, r, 0, sz, &e); } fn fold_raw(&mut self, i: usize, a: usize, b: usize, l: usize, r: usize) -> T { self.push(i, r - l); if b <= l || r <= a { T::identity() } else if a <= l && r <= b { self.node[i].clone() } else { self.fold_raw(i << 1, a, b, l, (l + r) >> 1) .op(&self.fold_raw((i << 1) + 1, a, b, (l + r) >> 1, r)) } } pub fn fold(&mut self, l: usize, r: usize) -> T { let sz = self.sz; self.fold_raw(1, l, r, 0, sz) } } #[derive(Clone)] struct Am { sum: usize, even: usize, odd: usize, } impl Magma for Am { fn op(&self, right: &Self) -> Self { Am { sum: self.sum + right.sum, even: self.even + right.even, odd: self.odd + right.odd, }} } impl Associative for Am {} impl Unital for Am { fn identity() -> Self { Am { sum: 0, even: 0, odd: 0, }} } #[derive(Clone)] enum Uq { Plus(usize), Update(usize, usize), } impl Magma for Uq { fn op(&self, right: &Self) -> Self { match self.clone() { Uq::Plus(x) => { match right.clone() { Uq::Plus(y) => Uq::Plus(x + y), Uq::Update(even, odd) => { if x % 2 == 0 { Uq::Update(even, odd) } else { Uq::Update(odd, even) } } } } Uq::Update(e, o) => { match right.clone() { Uq::Plus(y) => Uq::Update(e + y, o + y), Uq::Update(even, odd) => { if e % 2 == 0 { Uq::Update(even, odd) } else { Uq::Update(odd, even) } } } } } } } impl Associative for Uq {} impl Unital for Uq { fn identity() -> Self { Uq::Plus(0) } } impl Effector for Uq { type Target = Am; fn effect(&self, t: &Self::Target, len : usize) -> Self::Target { match self.clone() { Uq::Plus(x) => { if x % 2 == 0 { Am { sum: t.sum + len * x, even: t.even, odd: t.odd, } } else { Am { sum: t.sum + len * x, even: t.odd, odd: t.even, } } } Uq::Update(even, odd) => { Am { sum: t.even * even + t.odd * odd, even: if even % 2 == 0 { t.even } else { t.odd }, odd: if even % 2 == 0 { t.odd } else { t.even }, } } } } } use std::io::Read; fn main() { let mut buf = String::new(); std::io::stdin().read_to_string(&mut buf).unwrap(); let mut iter = buf.split_whitespace(); let n: usize = iter.next().unwrap().parse().unwrap(); let q: usize = iter.next().unwrap().parse().unwrap(); let mut vec = Vec::new(); for _ in 0..n { let a: usize = iter.next().unwrap().parse().unwrap(); if a % 2 == 0 { vec.push(Am { sum: a, even: 1, odd: 0 }); } else { vec.push(Am { sum: a, even: 0, odd: 1 }); } } let mut seg = LazySegmentTree::::init(vec); for _ in 0..q { let com: usize = iter.next().unwrap().parse().unwrap(); let l: usize = iter.next().unwrap().parse().unwrap(); let r: usize = iter.next().unwrap().parse().unwrap(); if com == 1 { seg.update_range(l - 1, r, Uq::Update(0, 1)); } else if com == 2 { let x: usize = iter.next().unwrap().parse().unwrap(); seg.update_range(l - 1, r, Uq::Plus(x)); } else { println!("{}", seg.fold(l - 1, r).sum); } } }