use super::algebra::{Act, Monoid};
use super::util::IntoIndex;
use std::iter::FromIterator;
use std::ptr;
pub struct LazySegTree<M: Monoid + Clone, A: Monoid + Act<M> + Clone>(Vec<(M, A)>);
impl<M: Monoid + Clone, A: Monoid + Act<M> + Clone> LazySegTree<M, A> {
fn size(&self) -> usize {
self.0.len() / 2
}
fn height(&self) -> u32 {
self.0.len().trailing_zeros()
}
fn act_lazy(node: &mut (M, A), a: &A) {
*node = (a.act(&node.0), a.op(&node.1));
}
fn propagate_to_children(&mut self, i: usize) {
let a = self.0[i].1.clone();
Self::act_lazy(&mut self.0[i * 2], &a);
Self::act_lazy(&mut self.0[i * 2 + 1], &a);
self.0[i].1 = A::ID;
}
fn propagate(&mut self, start: usize, end: usize) {
for i in (1..self.height()).rev() {
if (start >> i) << i != start {
self.propagate_to_children(start >> i);
}
if (end >> i) << i != end {
self.propagate_to_children((end - 1) >> i);
}
}
}
fn update(&mut self, i: usize) {
self.0[i].0 = self.0[i * 2].0.op(&self.0[i * 2 + 1].0);
}
}
impl<M: Monoid + Clone, A: Monoid + Act<M> + Clone> LazySegTree<M, A> {
pub fn new(size: usize) -> Self {
LazySegTree(vec![(M::ID, A::ID); size.next_power_of_two() * 2])
}
pub fn from_iter_sized<I: IntoIterator<Item = M>>(iter: I, size: usize) -> Self {
let mut iter = iter.into_iter();
let size = size.next_power_of_two();
let mut v = Vec::with_capacity(size * 2);
let v_ptr: *mut (M, A) = v.as_mut_ptr();
unsafe {
v.set_len(size * 2);
for i in 0..size {
ptr::write(
v_ptr.add(size + i),
if let Some(m) = iter.next() {
(m, A::ID)
} else {
(M::ID, A::ID)
},
);
}
for i in (1..size).rev() {
ptr::write(v_ptr.add(i), (v[i * 2].0.op(&v[i * 2 + 1].0), A::ID));
}
}
LazySegTree(v)
}
pub fn get<R>(&mut self, range: R) -> M
where
R: IntoIndex,
{
let (mut start, mut end) = range.into_index(self.size());
start += self.size();
end += self.size();
self.propagate(start, end);
let mut m = M::ID;
while start < end {
if start % 2 == 1 {
m = self.0[start].0.op(&m);
start += 1;
}
if end % 2 == 1 {
end -= 1;
m = self.0[end].0.op(&m);
}
start /= 2;
end /= 2;
}
m
}
pub fn set(&mut self, i: usize, m: M) {
let i = i + self.size();
for h in (1..=self.height()).rev() {
self.propagate_to_children(i >> h);
}
self.0[i] = (m, A::ID);
for h in 1..=self.height() {
self.update(i >> h);
}
}
pub fn act<R>(&mut self, range: R, a: A)
where
R: IntoIndex,
{
let (mut start, mut end) = range.into_index(self.size());
start += self.size();
end += self.size();
self.propagate(start, end);
{
let mut start = start;
let mut end = end;
while start < end {
if start % 2 == 1 {
Self::act_lazy(&mut self.0[start], &a);
start += 1;
}
if end % 2 == 1 {
end -= 1;
Self::act_lazy(&mut self.0[end], &a);
}
start /= 2;
end /= 2;
}
}
for i in 1..=self.height() {
if (start >> i) << i != start {
self.update(start >> i);
}
if (end >> i) << i != end {
self.update((end - 1) >> i);
}
}
}
}
impl<M, A> FromIterator<M> for LazySegTree<M, A>
where
M: Monoid + Clone,
A: Monoid + Act<M> + Clone,
{
fn from_iter<I: IntoIterator<Item = M>>(iter: I) -> Self {
let v: Vec<M> = iter.into_iter().collect();
let len = v.len();
LazySegTree::from_iter_sized(v, len)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Act;
#[derive(Clone, Debug, PartialEq, Eq)]
struct MinMax(i64, i64);
impl Monoid for MinMax {
const ID: Self = MinMax(i64::MAX, i64::MIN);
fn op(&self, rhs: &Self) -> Self {
MinMax(self.0.min(rhs.0), self.1.max(rhs.1))
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
struct Add(i64);
impl Monoid for Add {
const ID: Self = Add(0);
fn op(&self, rhs: &Self) -> Self {
Add(self.0.saturating_add(rhs.0))
}
}
impl Act<MinMax> for Add {
fn act(&self, m: &MinMax) -> MinMax {
if m == &MinMax::ID {
MinMax::ID
} else {
MinMax(m.0 + self.0, m.1 + self.0)
}
}
}
#[test]
fn min_max_and_range_add() {
let mut t: LazySegTree<MinMax, Add> = LazySegTree::new(8);
assert_eq!(t.get(..), MinMax::ID);
for i in 0..6 {
t.set(i, MinMax(0, 0));
}
t.act(0..=3, Add(5));
t.act(2..=5, Add(42));
assert_eq!(t.get(0..=1), MinMax(5, 5));
assert_eq!(t.get(1..=2), MinMax(5, 47));
assert_eq!(t.get(2..=3), MinMax(47, 47));
assert_eq!(t.get(3..=4), MinMax(42, 47));
assert_eq!(t.get(4..=5), MinMax(42, 42));
assert_eq!(t.get(5..=6), MinMax(42, 42));
assert_eq!(t.get(0..=5), MinMax(5, 47));
assert_eq!(t.get(6..=7), MinMax::ID);
assert_eq!(t.get(5), MinMax(42, 42));
}
#[test]
fn many_intervals() {
let mut t: LazySegTree<MinMax, Add> = LazySegTree::new(88);
for i in 0..88 {
t.set(i, MinMax(0, 0));
}
t.act(0..20, Add(5));
t.act(20..40, Add(42));
t.act(40..60, Add(-5));
t.act(60..88, Add(17));
t.act(10..70, Add(1));
assert_eq!(t.get(..), MinMax(-4, 43));
assert_eq!(t.get(0..20), MinMax(5, 6));
assert_eq!(t.get(70..88), MinMax(17, 17));
assert_eq!(t.get(40), MinMax(-4, -4));
}
}