From 6a6710cd27c9064f4117a84f9327cb4a92296615 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Thu, 16 Jun 2022 19:13:27 +0900 Subject: [PATCH 1/2] Construct segtree more efficiently --- src/lazysegtree.rs | 76 +++++++++++++++++++++++++++++++++++++++++----- src/segtree.rs | 62 ++++++++++++++++++++++++++++++++----- 2 files changed, 124 insertions(+), 14 deletions(-) diff --git a/src/lazysegtree.rs b/src/lazysegtree.rs index 47020a8..18db081 100644 --- a/src/lazysegtree.rs +++ b/src/lazysegtree.rs @@ -31,12 +31,28 @@ impl LazySegtree { } impl From::S>> for LazySegtree { fn from(v: Vec<::S>) -> Self { - let n = v.len(); + Self::from_vec(v, 0) + } +} + +impl LazySegtree { + /// Creates a segtree from elements `d[offset..]`. + fn from_vec(mut d: Vec<::S>, offset: usize) -> Self { + assert!(offset <= d.len()); + let n = d.len() - offset; let log = ceil_pow2(n as u32) as usize; let size = 1 << log; - let mut d = vec![F::identity_element(); 2 * size]; + match offset.cmp(&size) { + Ordering::Less => { + d.splice(0..0, repeat_with(F::identity_element).take(size - offset)); + } + Ordering::Equal => {} + Ordering::Greater => { + d.splice(size..offset, empty()); + } + }; + d.resize_with(size * 2, F::identity_element); let lz = vec![F::identity_map(); size]; - d[size..(size + n)].clone_from_slice(&v); let mut ret = LazySegtree { n, size, @@ -47,11 +63,11 @@ impl From::S>> for LazySegtree { for i in (1..size).rev() { ret.update(i); } + // `ret.d[0]` is uninitialized and has an unknown value. + // This is ok as it is unused (as of writing). ret } -} -impl LazySegtree { pub fn set(&mut self, mut p: usize, x: ::S) { assert!(p < self.n); p += self.size; @@ -287,7 +303,11 @@ where } // TODO is it useful? -use std::fmt::{Debug, Error, Formatter, Write}; +use std::{ + cmp::Ordering, + fmt::{Debug, Error, Formatter, Write}, + iter::{empty, repeat_with}, +}; impl Debug for LazySegtree where F: MapMonoid, @@ -314,7 +334,7 @@ where #[cfg(test)] mod tests { - use crate::{LazySegtree, MapMonoid, Max}; + use crate::{Additive, LazySegtree, MapMonoid, Max}; struct MaxAdd; impl MapMonoid for MaxAdd { @@ -413,4 +433,46 @@ mod tests { } } } + + #[test] + fn test_from_vec() { + struct IdAdditive; + impl MapMonoid for IdAdditive { + type M = Additive; + type F = (); + fn identity_map() {} + fn mapping(_: &(), &x: &u32) -> u32 { + x + } + fn composition(_: &(), _: &()) {} + } + + let v = vec![1, 2, 4]; + let ans_124 = vec![7, 3, 4, 1, 2, 4, 0]; + let tree = LazySegtree::::from_vec(v, 0); + assert_eq!(&tree.d[1..], &ans_124[..]); + + let v = vec![1, 2, 4, 8]; + let tree = LazySegtree::::from_vec(v, 0); + assert_eq!(&tree.d[1..], &vec![15, 3, 12, 1, 2, 4, 8][..]); + + let v = vec![1, 2, 4, 8, 16]; + let tree = LazySegtree::::from_vec(v, 0); + assert_eq!( + &tree.d[1..], + &vec![31, 15, 16, 3, 12, 16, 0, 1, 2, 4, 8, 16, 0, 0, 0][..] + ); + + let v = vec![314, 159, 265, 1, 2, 4]; + let tree = LazySegtree::::from_vec(v, 3); + assert_eq!(&tree.d[1..], &ans_124[..]); + + let v = vec![314, 159, 265, 897, 1, 2, 4]; + let tree = LazySegtree::::from_vec(v, 4); + assert_eq!(&tree.d[1..], &ans_124[..]); + + let v = vec![314, 159, 265, 897, 932, 1, 2, 4]; + let tree = LazySegtree::::from_vec(v, 5); + assert_eq!(&tree.d[1..], &ans_124[..]); + } } diff --git a/src/segtree.rs b/src/segtree.rs index b543aa3..d05c233 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -1,7 +1,8 @@ use crate::internal_bit::ceil_pow2; use crate::internal_type_traits::{BoundedAbove, BoundedBelow, One, Zero}; -use std::cmp::{max, min}; +use std::cmp::{max, min, Ordering}; use std::convert::Infallible; +use std::iter::{empty, repeat_with}; use std::marker::PhantomData; use std::ops::{Add, Mul}; @@ -80,19 +81,35 @@ impl Segtree { } impl From> for Segtree { fn from(v: Vec) -> Self { - let n = v.len(); + Self::from_vec(v, 0) + } +} +impl Segtree { + /// Creates a segtree from elements `d[offset..]`. + fn from_vec(mut d: Vec, offset: usize) -> Self { + assert!(offset <= d.len()); + let n = d.len() - offset; let log = ceil_pow2(n as u32) as usize; let size = 1 << log; - let mut d = vec![M::identity(); 2 * size]; - d[size..(size + n)].clone_from_slice(&v); + match offset.cmp(&size) { + Ordering::Less => { + d.splice(0..0, repeat_with(M::identity).take(size - offset)); + } + Ordering::Equal => {} + Ordering::Greater => { + d.splice(size..offset, empty()); + } + }; + d.resize_with(size * 2, M::identity); let mut ret = Segtree { n, size, log, d }; for i in (1..size).rev() { ret.update(i); } + // `ret.d[0]` is uninitialized and has an unknown value. + // This is ok as it is unused (as of writing). ret } -} -impl Segtree { + pub fn set(&mut self, mut p: usize, x: M::S) { assert!(p < self.n); p += self.size; @@ -238,7 +255,7 @@ where #[cfg(test)] mod tests { - use crate::segtree::Max; + use crate::segtree::{Additive, Max}; use crate::Segtree; #[test] @@ -312,4 +329,35 @@ mod tests { } } } + + #[test] + fn test_from_vec() { + let v = vec![1, 2, 4]; + let ans_124 = vec![7, 3, 4, 1, 2, 4, 0]; + let tree = Segtree::>::from_vec(v, 0); + assert_eq!(&tree.d[1..], &ans_124[..]); + + let v = vec![1, 2, 4, 8]; + let tree = Segtree::>::from_vec(v, 0); + assert_eq!(&tree.d[1..], &vec![15, 3, 12, 1, 2, 4, 8][..]); + + let v = vec![1, 2, 4, 8, 16]; + let tree = Segtree::>::from_vec(v, 0); + assert_eq!( + &tree.d[1..], + &vec![31, 15, 16, 3, 12, 16, 0, 1, 2, 4, 8, 16, 0, 0, 0][..] + ); + + let v = vec![314, 159, 265, 1, 2, 4]; + let tree = Segtree::>::from_vec(v, 3); + assert_eq!(&tree.d[1..], &ans_124[..]); + + let v = vec![314, 159, 265, 897, 1, 2, 4]; + let tree = Segtree::>::from_vec(v, 4); + assert_eq!(&tree.d[1..], &ans_124[..]); + + let v = vec![314, 159, 265, 897, 932, 1, 2, 4]; + let tree = Segtree::>::from_vec(v, 5); + assert_eq!(&tree.d[1..], &ans_124[..]); + } } From 2e1aa034bc402ff856e376a0b193630e48e031ec Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Thu, 16 Jun 2022 19:27:27 +0900 Subject: [PATCH 2/2] Implement FromIterator for segtrees --- src/lazysegtree.rs | 21 ++++++++++++++++++++- src/segtree.rs | 21 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/lazysegtree.rs b/src/lazysegtree.rs index 18db081..8a75924 100644 --- a/src/lazysegtree.rs +++ b/src/lazysegtree.rs @@ -34,6 +34,17 @@ impl From::S>> for LazySegtree { Self::from_vec(v, 0) } } +impl FromIterator<::S> for LazySegtree { + fn from_iter::S>>(iter: T) -> Self { + let iter = iter.into_iter(); + let n = iter.size_hint().0; + let log = ceil_pow2(n as u32) as usize; + let size = 1 << log; + let mut d = Vec::with_capacity(size * 2); + d.extend(repeat_with(F::identity_element).take(size).chain(iter)); + Self::from_vec(d, size) + } +} impl LazySegtree { /// Creates a segtree from elements `d[offset..]`. @@ -306,7 +317,7 @@ where use std::{ cmp::Ordering, fmt::{Debug, Error, Formatter, Write}, - iter::{empty, repeat_with}, + iter::{empty, repeat_with, FromIterator}, }; impl Debug for LazySegtree where @@ -386,6 +397,14 @@ mod tests { check_segtree(&internal, &mut segtree); } + #[test] + fn test_from_iter() { + let it = || (1..7).map(|x| x * 4 % 11); + let base = it().collect::>(); + let mut segtree: LazySegtree = it().collect(); + check_segtree(&base, &mut segtree); + } + //noinspection DuplicatedCode fn check_segtree(base: &[i32], segtree: &mut LazySegtree) { let n = base.len(); diff --git a/src/segtree.rs b/src/segtree.rs index d05c233..189605a 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -2,7 +2,7 @@ use crate::internal_bit::ceil_pow2; use crate::internal_type_traits::{BoundedAbove, BoundedBelow, One, Zero}; use std::cmp::{max, min, Ordering}; use std::convert::Infallible; -use std::iter::{empty, repeat_with}; +use std::iter::{empty, repeat_with, FromIterator}; use std::marker::PhantomData; use std::ops::{Add, Mul}; @@ -84,6 +84,17 @@ impl From> for Segtree { Self::from_vec(v, 0) } } +impl FromIterator for Segtree { + fn from_iter>(iter: T) -> Self { + let iter = iter.into_iter(); + let n = iter.size_hint().0; + let log = ceil_pow2(n as u32) as usize; + let size = 1 << log; + let mut d = Vec::with_capacity(size * 2); + d.extend(repeat_with(M::identity).take(size).chain(iter)); + Self::from_vec(d, size) + } +} impl Segtree { /// Creates a segtree from elements `d[offset..]`. fn from_vec(mut d: Vec, offset: usize) -> Self { @@ -282,6 +293,14 @@ mod tests { check_segtree(&internal, &segtree); } + #[test] + fn test_from_iter() { + let it = || (1..7).map(|x| x * 4 % 11); + let base = it().collect::>(); + let segtree: Segtree> = it().collect(); + check_segtree(&base, &segtree); + } + //noinspection DuplicatedCode fn check_segtree(base: &[i32], segtree: &Segtree>) { let n = base.len();