From 0e8242f86b5de5e43986d79d6e19c81ae4cbf3a9 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Fri, 11 Sep 2020 22:02:36 +0900 Subject: [PATCH 01/27] Initial commit for segtree --- src/segtree.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/segtree.rs b/src/segtree.rs index 8b13789..8754481 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -1 +1,2 @@ - +struct Segtree { +} \ No newline at end of file From 452f9f15fa0e07e7037665c5ef30361417cab3d2 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 00:12:04 +0900 Subject: [PATCH 02/27] Added segtree --- src/lib.rs | 1 + src/segtree.rs | 164 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 163 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5855a09..a93bbfe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ pub use dsu::Dsu; pub use fenwicktree::FenwickTree; pub use math::{crt, floor_sum, inv_mod, pow_mod}; pub use mincostflow::MinCostFlowGraph; +pub use segtree::{Monoid, Segtree}; pub use string::{ lcp_array, lcp_array_arbitrary, suffix_array, suffix_array_arbitrary, suffix_array_manual, z_algorithm, z_algorithm_arbitrary, diff --git a/src/segtree.rs b/src/segtree.rs index 8754481..9956147 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -1,2 +1,162 @@ -struct Segtree { -} \ No newline at end of file +use crate::internal_bit::ceil_pow2; + +pub trait Monoid { + type S: Copy; + const IDENTITY: Self::S; + fn binary_operation(a: Self::S, b: Self::S) -> Self::S; +} + +impl Segtree { + pub fn new(n: usize) -> Segtree { + vec![M::IDENTITY; n].into() + } +} +impl From> for Segtree { + fn from(v: Vec) -> Self { + let n = v.len(); + let log = ceil_pow2(n as u32) as usize; + let size = 1 << log; + let mut d = vec![M::IDENTITY; n]; + d[size..(n + size)].clone_from_slice(&v[..n]); + let mut ret = Segtree { n, size, log, d }; + for i in (1..n).rev() { + ret.update(i); + } + ret + } +} + +impl Segtree { + pub fn set(&mut self, mut p: usize, x: M::S) { + assert!(p <= self.n); + p += self.size; + self.d[p] = x; + for i in 1..=self.log { + self.update(p >> i); + } + } + + pub fn get(&self, p: usize) -> M::S { + assert!(p <= self.n); + self.d[p + self.size] + } + + pub fn prod(&self, mut l: usize, mut r: usize) -> M::S { + assert!(l <= r && r <= self.n); + let mut sml = M::IDENTITY; + let mut smr = M::IDENTITY; + l += self.size; + r += self.size; + + while l < r { + if l & 1 != 0 { + sml = M::binary_operation(sml, self.d[l]); + l += 1; + } + if r & 1 != 0 { + r -= 1; + smr = M::binary_operation(self.d[r], smr); + } + l >>= 1; + r >>= 1; + } + + M::binary_operation(sml, smr) + } + + pub fn all_prod(&self) -> M::S { + self.d[1] + } + + pub fn max_right(&self, mut l: usize, f: F) -> usize + where + F: Fn(M::S) -> bool, + { + assert!(l <= self.n); + assert!(f(M::IDENTITY)); + if l == self.n { + return self.n; + } + l += self.size; + let mut sm = M::IDENTITY; + while { + // do + while l % 2 == 0 { + l >>= 1; + } + if !f(M::binary_operation(sm, self.d[l])) { + while l < self.size { + l *= 2; + let res = M::binary_operation(sm, self.d[l]); + if f(res) { + sm = res; + l += 1; + } + } + return l - self.size; + } + sm = M::binary_operation(sm, self.d[l]); + l += 1; + // while + { + let l = l as isize; + (l & -l) != l + } + } {} + self.n + } + + pub fn min_left(&self, mut r: usize, f: F) -> usize + where + F: Fn(M::S) -> bool, + { + assert!(r <= self.n); + assert!(f(M::IDENTITY)); + if r == 0 { + return 0; + } + r += self.size; + let mut sm = M::IDENTITY; + while { + // do + r -= 1; + while r > 1 && r % 2 == 1 { + r >>= 1; + } + if !f(M::binary_operation(self.d[r], sm)) { + while r < self.size { + r = 2 * r + 1; + let res = M::binary_operation(self.d[r], sm); + if f(res) { + sm = res; + r -= 1; + } + } + return r + 1 - self.size; + } + sm = M::binary_operation(self.d[r], sm); + // while + { + let r = r as isize; + (r & -r) != r + } + } {} + 0 + } + + fn update(&mut self, k: usize) { + self.d[k] = M::binary_operation(self.d[2 * k], self.d[2 * k + 1]); + } +} + +#[derive(Default)] +pub struct Segtree +where + M: Monoid, +{ + // variable name is _n in original library + n: usize, + size: usize, + log: usize, + d: Vec, +} From c35995ecf21436d8da9294849a971b25f486ac9d Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 00:13:35 +0900 Subject: [PATCH 03/27] Removed newline --- src/segtree.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/segtree.rs b/src/segtree.rs index 9956147..2ba8969 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -25,7 +25,6 @@ impl From> for Segtree { ret } } - impl Segtree { pub fn set(&mut self, mut p: usize, x: M::S) { assert!(p <= self.n); From 831c35a9c91f7eaeb1c47322417911c44b1b864f Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 00:21:22 +0900 Subject: [PATCH 04/27] Fixed mistakes --- src/segtree.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/segtree.rs b/src/segtree.rs index 2ba8969..da5391b 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -16,8 +16,8 @@ impl From> for Segtree { let n = v.len(); let log = ceil_pow2(n as u32) as usize; let size = 1 << log; - let mut d = vec![M::IDENTITY; n]; - d[size..(n + size)].clone_from_slice(&v[..n]); + let mut d = vec![M::IDENTITY; 2 * size]; + d[size..(size + n)].clone_from_slice(&v); let mut ret = Segtree { n, size, log, d }; for i in (1..n).rev() { ret.update(i); @@ -27,7 +27,7 @@ impl From> for Segtree { } impl Segtree { pub fn set(&mut self, mut p: usize, x: M::S) { - assert!(p <= self.n); + assert!(p < self.n); p += self.size; self.d[p] = x; for i in 1..=self.log { @@ -36,7 +36,7 @@ impl Segtree { } pub fn get(&self, p: usize) -> M::S { - assert!(p <= self.n); + assert!(p < self.n); self.d[p + self.size] } From db3e57f865245d3f363e54531f7cb58f476302f0 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 02:08:52 +0900 Subject: [PATCH 05/27] Change identity from constant to function --- src/segtree.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/segtree.rs b/src/segtree.rs index da5391b..58dac41 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -1,14 +1,15 @@ use crate::internal_bit::ceil_pow2; +// TODO Should I split monoid-related traits to another module? pub trait Monoid { type S: Copy; - const IDENTITY: Self::S; + fn identity() -> Self::S; fn binary_operation(a: Self::S, b: Self::S) -> Self::S; } impl Segtree { pub fn new(n: usize) -> Segtree { - vec![M::IDENTITY; n].into() + vec![M::identity(); n].into() } } impl From> for Segtree { @@ -16,10 +17,10 @@ impl From> for Segtree { let n = v.len(); let log = ceil_pow2(n as u32) as usize; let size = 1 << log; - let mut d = vec![M::IDENTITY; 2 * size]; + let mut d = vec![M::identity(); 2 * size]; d[size..(size + n)].clone_from_slice(&v); let mut ret = Segtree { n, size, log, d }; - for i in (1..n).rev() { + for i in (1..size).rev() { ret.update(i); } ret @@ -42,8 +43,8 @@ impl Segtree { pub fn prod(&self, mut l: usize, mut r: usize) -> M::S { assert!(l <= r && r <= self.n); - let mut sml = M::IDENTITY; - let mut smr = M::IDENTITY; + let mut sml = M::identity(); + let mut smr = M::identity(); l += self.size; r += self.size; @@ -72,12 +73,12 @@ impl Segtree { F: Fn(M::S) -> bool, { assert!(l <= self.n); - assert!(f(M::IDENTITY)); + assert!(f(M::identity())); if l == self.n { return self.n; } l += self.size; - let mut sm = M::IDENTITY; + let mut sm = M::identity(); while { // do while l % 2 == 0 { @@ -110,12 +111,12 @@ impl Segtree { F: Fn(M::S) -> bool, { assert!(r <= self.n); - assert!(f(M::IDENTITY)); + assert!(f(M::identity())); if r == 0 { return 0; } r += self.size; - let mut sm = M::IDENTITY; + let mut sm = M::identity(); while { // do r -= 1; From 7f708282468934f1492b1e6bdeaea0c2b62c1833 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 03:06:38 +0900 Subject: [PATCH 06/27] Added "Max" monoid and a test --- src/segtree.rs | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/src/segtree.rs b/src/segtree.rs index 58dac41..a6eb5a2 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -1,4 +1,7 @@ use crate::internal_bit::ceil_pow2; +use crate::internal_type_traits::Integral; +use std::cmp::max; +use std::marker::PhantomData; // TODO Should I split monoid-related traits to another module? pub trait Monoid { @@ -6,6 +9,23 @@ pub trait Monoid { fn identity() -> Self::S; fn binary_operation(a: Self::S, b: Self::S) -> Self::S; } +pub struct Max(PhantomData S>); + +// TODO We should not restrict to integral +impl Monoid for Max +where + S: Integral, +{ + type S = S; + + fn identity() -> Self::S { + S::min_value() + } + + fn binary_operation(a: Self::S, b: Self::S) -> Self::S { + max(a, b) + } +} impl Segtree { pub fn new(n: usize) -> Segtree { @@ -149,6 +169,16 @@ impl Segtree { } } +// Maybe we can use this someday +// ``` +// for i in 0..=self.log { +// for j in 0..1 << i { +// print!("{}\t", self.d[(1 << i) + j]); +// } +// println!(); +// } +// ``` + #[derive(Default)] pub struct Segtree where @@ -160,3 +190,80 @@ where log: usize, d: Vec, } + +#[cfg(test)] +mod test { + use crate::segtree::Max; + use crate::Segtree; + + #[test] + fn test_max_from_vec() { + let base = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3]; + let n = base.len(); + let segtree: Segtree> = base.clone().into(); + check_segtree(&base, &segtree); + + let mut segtree = Segtree::>::new(n); + let mut internal = vec![i32::min_value(); n]; + for i in 0..n { + segtree.set(i, base[i]); + internal[i] = base[i]; + check_segtree(&internal, &segtree); + } + + segtree.set(6, 5); + internal[6] = 5; + check_segtree(&internal, &segtree); + + segtree.set(6, 0); + internal[6] = 0; + check_segtree(&internal, &segtree); + } + + fn check_segtree(base: &[i32], segtree: &Segtree>) { + let n = base.len(); + #[allow(clippy::needless_range_loop)] + for i in 0..n { + assert_eq!(segtree.get(i), base[i]); + } + for i in 0..=n { + for j in i..=n { + assert_eq!( + segtree.prod(i, j), + base[i..j].iter().max().copied().unwrap_or(i32::min_value()) + ); + } + } + assert_eq!( + segtree.all_prod(), + base.iter().max().copied().unwrap_or(i32::min_value()) + ); + for k in 0..=10 { + let f = |x| x < k; + for i in 0..=n { + assert_eq!( + Some(segtree.max_right(i, f)), + (i..=n) + .filter(|&j| f(base[i..j] + .iter() + .max() + .copied() + .unwrap_or(i32::min_value()))) + .max() + ); + } + for j in 0..=n { + assert_eq!( + Some(segtree.min_left(j, f)), + (0..=j) + .filter(|&i| f(base[i..j] + .iter() + .max() + .copied() + .unwrap_or(i32::min_value()))) + .min() + ); + } + } + } +} From b27d10dea2b851cc9a7302fc94d6f5f14a3bb3c7 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 03:42:28 +0900 Subject: [PATCH 07/27] Added sample for J - Segment Tree --- examples/practice2_j_segment_tree.rs | 35 ++++++++++++++++++++++++++++ src/lib.rs | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 examples/practice2_j_segment_tree.rs diff --git a/examples/practice2_j_segment_tree.rs b/examples/practice2_j_segment_tree.rs new file mode 100644 index 0000000..7d4b277 --- /dev/null +++ b/examples/practice2_j_segment_tree.rs @@ -0,0 +1,35 @@ +use ac_library_rs::{Max, Segtree}; +use std::io::Read; + +fn main() { + let mut buf = String::new(); + std::io::stdin().read_to_string(&mut buf).unwrap(); + let mut input = buf.split_whitespace(); + + let n: usize = input.next().unwrap().parse().unwrap(); + let q: usize = input.next().unwrap().parse().unwrap(); + let mut segtree = Segtree::>::new(n+1); + for i in 1..=n { + segtree.set(i, input.next().unwrap().parse().unwrap()); + } + for _ in 0..q { + match input.next().unwrap().parse().unwrap() { + 1 => { + let x = input.next().unwrap().parse().unwrap(); + let v = input.next().unwrap().parse().unwrap(); + segtree.set(x, v); + } + 2 => { + let l = input.next().unwrap().parse().unwrap(); + let r: usize = input.next().unwrap().parse().unwrap(); + println!("{}", segtree.prod(l, r+1)); + } + 3 => { + let x = input.next().unwrap().parse().unwrap(); + let v = input.next().unwrap().parse().unwrap(); + println!("{}", segtree.max_right(x, |a| a < v)) + } + _ => {} + } + } +} diff --git a/src/lib.rs b/src/lib.rs index c7b0be4..64a038e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ pub use modint::{ ModInt998244353, Modulus, RemEuclidU32, StaticModInt, }; pub use scc::SccGraph; -pub use segtree::{Monoid, Segtree}; +pub use segtree::{Monoid, Segtree, Max}; pub use string::{ lcp_array, lcp_array_arbitrary, suffix_array, suffix_array_arbitrary, suffix_array_manual, z_algorithm, z_algorithm_arbitrary, From 167cee8765ea1b0ec82ecd3c5c29ce07b636b44a Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 03:43:25 +0900 Subject: [PATCH 08/27] cargo fmt --- examples/practice2_j_segment_tree.rs | 4 ++-- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/practice2_j_segment_tree.rs b/examples/practice2_j_segment_tree.rs index 7d4b277..961efc8 100644 --- a/examples/practice2_j_segment_tree.rs +++ b/examples/practice2_j_segment_tree.rs @@ -8,7 +8,7 @@ fn main() { let n: usize = input.next().unwrap().parse().unwrap(); let q: usize = input.next().unwrap().parse().unwrap(); - let mut segtree = Segtree::>::new(n+1); + let mut segtree = Segtree::>::new(n + 1); for i in 1..=n { segtree.set(i, input.next().unwrap().parse().unwrap()); } @@ -22,7 +22,7 @@ fn main() { 2 => { let l = input.next().unwrap().parse().unwrap(); let r: usize = input.next().unwrap().parse().unwrap(); - println!("{}", segtree.prod(l, r+1)); + println!("{}", segtree.prod(l, r + 1)); } 3 => { let x = input.next().unwrap().parse().unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 64a038e..4d878c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ pub use modint::{ ModInt998244353, Modulus, RemEuclidU32, StaticModInt, }; pub use scc::SccGraph; -pub use segtree::{Monoid, Segtree, Max}; +pub use segtree::{Max, Monoid, Segtree}; pub use string::{ lcp_array, lcp_array_arbitrary, suffix_array, suffix_array_arbitrary, suffix_array_manual, z_algorithm, z_algorithm_arbitrary, From 6a6259f40b5ee2394f70febc3323151791c765e0 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 14:12:04 +0900 Subject: [PATCH 09/27] Fixed Default implementation --- src/segtree.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/segtree.rs b/src/segtree.rs index a6eb5a2..9ff15b9 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -27,6 +27,11 @@ where } } +impl Default for Segtree { + fn default() -> Self { + Segtree::new(0) + } +} impl Segtree { pub fn new(n: usize) -> Segtree { vec![M::identity(); n].into() @@ -179,7 +184,6 @@ impl Segtree { // } // ``` -#[derive(Default)] pub struct Segtree where M: Monoid, From dc1c6b75630e4b8a70b2a9ea40e52a5a388f756a Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 14:16:36 +0900 Subject: [PATCH 10/27] Changed Copy to Clone --- src/segtree.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/segtree.rs b/src/segtree.rs index 9ff15b9..600513c 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -5,7 +5,7 @@ use std::marker::PhantomData; // TODO Should I split monoid-related traits to another module? pub trait Monoid { - type S: Copy; + type S: Clone; fn identity() -> Self::S; fn binary_operation(a: Self::S, b: Self::S) -> Self::S; } @@ -63,7 +63,7 @@ impl Segtree { pub fn get(&self, p: usize) -> M::S { assert!(p < self.n); - self.d[p + self.size] + self.d[p + self.size].clone() } pub fn prod(&self, mut l: usize, mut r: usize) -> M::S { @@ -75,12 +75,12 @@ impl Segtree { while l < r { if l & 1 != 0 { - sml = M::binary_operation(sml, self.d[l]); + sml = M::binary_operation(sml, self.d[l].clone()); l += 1; } if r & 1 != 0 { r -= 1; - smr = M::binary_operation(self.d[r], smr); + smr = M::binary_operation(self.d[r].clone(), smr); } l >>= 1; r >>= 1; @@ -90,7 +90,7 @@ impl Segtree { } pub fn all_prod(&self) -> M::S { - self.d[1] + self.d[1].clone() } pub fn max_right(&self, mut l: usize, f: F) -> usize @@ -109,18 +109,18 @@ impl Segtree { while l % 2 == 0 { l >>= 1; } - if !f(M::binary_operation(sm, self.d[l])) { + if !f(M::binary_operation(sm.clone(), self.d[l].clone())) { while l < self.size { l *= 2; - let res = M::binary_operation(sm, self.d[l]); - if f(res) { + let res = M::binary_operation(sm.clone(), self.d[l].clone()); + if f(res.clone()) { sm = res; l += 1; } } return l - self.size; } - sm = M::binary_operation(sm, self.d[l]); + sm = M::binary_operation(sm.clone(), self.d[l].clone()); l += 1; // while { @@ -148,18 +148,18 @@ impl Segtree { while r > 1 && r % 2 == 1 { r >>= 1; } - if !f(M::binary_operation(self.d[r], sm)) { + if !f(M::binary_operation(self.d[r].clone(), sm.clone())) { while r < self.size { r = 2 * r + 1; - let res = M::binary_operation(self.d[r], sm); - if f(res) { + let res = M::binary_operation(self.d[r].clone(), sm.clone()); + if f(res.clone()) { sm = res; r -= 1; } } return r + 1 - self.size; } - sm = M::binary_operation(self.d[r], sm); + sm = M::binary_operation(self.d[r].clone(), sm.clone()); // while { let r = r as isize; @@ -170,7 +170,7 @@ impl Segtree { } fn update(&mut self, k: usize) { - self.d[k] = M::binary_operation(self.d[2 * k], self.d[2 * k + 1]); + self.d[k] = M::binary_operation(self.d[2 * k].clone(), self.d[2 * k + 1].clone()); } } From ded9a93b5312cc2aeeb1bc1451ac9b20173ad6bf Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 15:09:13 +0900 Subject: [PATCH 11/27] Added LazySegTree --- src/lazysegtree.rs | 286 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 287 insertions(+) diff --git a/src/lazysegtree.rs b/src/lazysegtree.rs index 8b13789..af16f50 100644 --- a/src/lazysegtree.rs +++ b/src/lazysegtree.rs @@ -1 +1,287 @@ +use crate::internal_bit::ceil_pow2; +use crate::Monoid; +pub trait MapMonoid { + type M: Monoid; + type F: Copy; + // type S = ::S; + fn identity_element() -> ::S { + Self::M::identity() + } + fn binary_operation( + a: ::S, + b: ::S, + ) -> ::S { + Self::M::binary_operation(a, b) + } + fn identity_map() -> Self::F; + fn mapping(f: Self::F, x: ::S) -> ::S; + fn composition(f: Self::F, g: Self::F) -> Self::F; +} + +impl Default for LazySegtree { + fn default() -> Self { + Self::new(0) + } +} +impl LazySegtree { + pub fn new(n: usize) -> Self { + vec![F::identity_element(); n].into() + } +} +impl From::S>> for LazySegtree { + fn from(v: Vec<::S>) -> Self { + let n = v.len(); + let log = ceil_pow2(n as u32) as usize; + let size = 1 << log; + let mut d = vec![F::identity_element(); 2 * size]; + let lz = vec![F::identity_map(); size]; + d[size..(size + n)].clone_from_slice(&v); + let mut ret = LazySegtree { + n, + size, + log, + d, + lz, + }; + for i in (1..size).rev() { + ret.update(i); + } + ret + } +} + +impl LazySegtree { + pub fn set(&mut self, mut p: usize, x: ::S) { + assert!(p < self.n); + p += self.size; + for i in (1..=self.log).rev() { + self.push(p >> i); + } + self.d[p] = x; + for i in 1..=self.log { + self.update(p >> i); + } + } + + pub fn get(&mut self, mut p: usize) -> ::S { + assert!(p < self.n); + p += self.size; + for i in (1..=self.log).rev() { + self.push(p >> i); + } + self.d[p].clone() + } + + pub fn prod(&mut self, mut l: usize, mut r: usize) -> ::S { + assert!(l <= r && r <= self.n); + if l == r { + return F::identity_element(); + } + + l += self.size; + r += self.size; + + for i in (1..=self.log).rev() { + if ((l >> i) << i) != l { + self.push(l >> i); + } + if ((r >> i) << i) != r { + self.push(r >> i); + } + } + + let mut sml = F::identity_element(); + let mut smr = F::identity_element(); + while l < r { + if l & 1 != 0 { + sml = F::binary_operation(sml, self.d[l].clone()); + l += 1; + } + if r & 1 != 0 { + r -= 1; + smr = F::binary_operation(self.d[r].clone(), smr); + } + l >>= 1; + r >>= 1; + } + + F::binary_operation(sml, smr) + } + + pub fn all_prod(&self) -> ::S { + self.d[1].clone() + } + + pub fn apply(&mut self, mut p: usize, f: F::F) { + assert!(p < self.n); + p += self.size; + for i in (1..=self.log).rev() { + self.push(p >> i); + } + self.d[p] = F::mapping(f, self.d[p].clone()); + for i in 1..=self.log { + self.update(p >> i); + } + } + pub fn apply_range(&mut self, mut l: usize, mut r: usize, f: F::F) { + assert!(l <= r && r <= self.n); + if l == r { + return; + } + + l += self.size; + r += self.size; + + for i in (1..=self.log).rev() { + if ((l >> i) << i) != l { + self.push(l >> i); + } + if ((r >> i) << i) != r { + self.push((r - 1) >> i); + } + } + + { + let l2 = l; + let r2 = r; + while l < r { + if l & 1 != 0 { + self.all_apply(l, f.clone()); + l += 1; + } + if r & 1 != 0 { + r -= 1; + self.all_apply(r, f.clone()); + } + l >>= 1; + r >>= 1; + } + l = l2; + r = r2; + } + + for i in 1..=self.log { + if ((l >> i) << i) != l { + self.update(l >> i); + } + if ((r >> i) << i) != r { + self.update((r - 1) >> i); + } + } + } + + pub fn max_right(&mut self, mut l: usize, g: G) -> usize + where + G: Fn(::S) -> bool, + { + assert!(l <= self.n); + assert!(g(F::identity_element())); + if l == self.n { + return self.n; + } + l += self.size; + for i in (1..=self.log).rev() { + self.push(l >> i); + } + let mut sm = F::identity_element(); + while { + // do + while l % 2 == 0 { + l >>= 1; + } + if !g(F::binary_operation(sm.clone(), self.d[l].clone())) { + while l < self.size { + self.push(l); + l *= 2; + let res = F::binary_operation(sm.clone(), self.d[l].clone()); + if g(res.clone()) { + sm = res; + l += 1; + } + } + return l - self.size; + } + sm = F::binary_operation(sm, self.d[l].clone()); + l += 1; + //while + { + let l = l as isize; + (l & -l) != l + } + } {} + self.n + } + + pub fn min_left(&mut self, mut r: usize, g: G) -> usize + where + G: Fn(::S) -> bool, + { + assert!(r <= self.n); + assert!(g(F::identity_element())); + if r == 0 { + return self.n; + } + r += self.size; + for i in (1..=self.log).rev() { + self.push((r - 1) >> i); + } + let mut sm = F::identity_element(); + while { + // do + r -= 1; + while r > 1 && r % 2 != 0 { + r >>= 1; + } + if !g(F::binary_operation(self.d[r].clone(), sm.clone())) { + while r < self.size { + self.push(r); + r = 2 * r + 1; + let res = F::binary_operation(self.d[r].clone(), sm.clone()); + if g(res.clone()) { + sm = res; + r -= 1; + } + } + return r + 1 - self.size; + } + sm = F::binary_operation(self.d[r].clone(), sm); + // while + { + let r = r as isize; + (r & -r) != r + } + } {} + 0 + } +} + +pub struct LazySegtree +where + F: MapMonoid, +{ + n: usize, + size: usize, + log: usize, + d: Vec<::S>, + lz: Vec, +} +impl LazySegtree +where + F: MapMonoid, +{ + fn update(&mut self, k: usize) { + self.d[k] = F::binary_operation(self.d[2 * k].clone(), self.d[2 * k + 1].clone()); + } + fn all_apply(&mut self, k: usize, f: F::F) { + self.d[k] = F::mapping(f, self.d[k].clone()); + if k < self.size { + self.lz[k] = F::composition(f, self.lz[k]); + } + } + fn push(&mut self, k: usize) { + self.all_apply(2 * k, self.lz[k]); + self.all_apply(2 * k + 1, self.lz[k]); + self.lz[k] = F::identity_map(); + } +} diff --git a/src/lib.rs b/src/lib.rs index 4d878c9..989e799 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ pub(crate) mod internal_type_traits; pub use dsu::Dsu; pub use fenwicktree::FenwickTree; +pub use lazysegtree::{LazySegtree, MapMonoid}; pub use math::{crt, floor_sum, inv_mod, pow_mod}; pub use mincostflow::MinCostFlowGraph; pub use modint::{ From 34744605c75669269bde774197e82737776b0a51 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 15:13:20 +0900 Subject: [PATCH 12/27] Make MapMonoid underlying type Clone --- src/lazysegtree.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lazysegtree.rs b/src/lazysegtree.rs index af16f50..d6a183c 100644 --- a/src/lazysegtree.rs +++ b/src/lazysegtree.rs @@ -3,7 +3,7 @@ use crate::Monoid; pub trait MapMonoid { type M: Monoid; - type F: Copy; + type F: Clone; // type S = ::S; fn identity_element() -> ::S { Self::M::identity() @@ -274,14 +274,14 @@ where self.d[k] = F::binary_operation(self.d[2 * k].clone(), self.d[2 * k + 1].clone()); } fn all_apply(&mut self, k: usize, f: F::F) { - self.d[k] = F::mapping(f, self.d[k].clone()); + self.d[k] = F::mapping(f.clone(), self.d[k].clone()); if k < self.size { - self.lz[k] = F::composition(f, self.lz[k]); + self.lz[k] = F::composition(f, self.lz[k].clone()); } } fn push(&mut self, k: usize) { - self.all_apply(2 * k, self.lz[k]); - self.all_apply(2 * k + 1, self.lz[k]); + self.all_apply(2 * k, self.lz[k].clone()); + self.all_apply(2 * k + 1, self.lz[k].clone()); self.lz[k] = F::identity_map(); } } From a8b2cb6aa3b61f83fd3d82f551d361d4e0ebc4f8 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 16:53:42 +0900 Subject: [PATCH 13/27] Fix a mistake --- src/lazysegtree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lazysegtree.rs b/src/lazysegtree.rs index d6a183c..0614b7d 100644 --- a/src/lazysegtree.rs +++ b/src/lazysegtree.rs @@ -220,7 +220,7 @@ impl LazySegtree { assert!(r <= self.n); assert!(g(F::identity_element())); if r == 0 { - return self.n; + return 0; } r += self.size; for i in (1..=self.log).rev() { From e6ac534d2157cc258d21b95c179c06a13a03def9 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 16:56:08 +0900 Subject: [PATCH 14/27] Renamme test function --- src/segtree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segtree.rs b/src/segtree.rs index 600513c..e11c417 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -201,7 +201,7 @@ mod test { use crate::Segtree; #[test] - fn test_max_from_vec() { + fn test_max_segtree() { let base = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3]; let n = base.len(); let segtree: Segtree> = base.clone().into(); From 336bf185e75379a1c4448180aa2f916a157578e5 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 17:13:10 +0900 Subject: [PATCH 15/27] Added a test --- src/lazysegtree.rs | 103 +++++++++++++++++++++++++++++++++++++++++++++ src/segtree.rs | 1 + 2 files changed, 104 insertions(+) diff --git a/src/lazysegtree.rs b/src/lazysegtree.rs index 0614b7d..1934ea2 100644 --- a/src/lazysegtree.rs +++ b/src/lazysegtree.rs @@ -285,3 +285,106 @@ where self.lz[k] = F::identity_map(); } } + +#[cfg(test)] +mod tests { + use crate::{LazySegtree, MapMonoid, Max}; + + struct MaxAdd; + impl MapMonoid for MaxAdd { + type M = Max; + type F = i32; + + fn identity_map() -> Self::F { + 0 + } + + fn mapping(f: i32, x: i32) -> i32 { + f + x + } + + fn composition(f: i32, g: i32) -> i32 { + f + g + } + } + + #[test] + fn test_max_add_lazy_segtree() { + let base = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3]; + let n = base.len(); + let mut segtree: LazySegtree = base.clone().into(); + check_segtree(&base, &mut segtree); + + let mut segtree = LazySegtree::::new(n); + let mut internal = vec![i32::min_value(); n]; + for i in 0..n { + segtree.set(i, base[i]); + internal[i] = base[i]; + check_segtree(&internal, &mut segtree); + } + + segtree.set(6, 5); + internal[6] = 5; + check_segtree(&internal, &mut segtree); + + segtree.apply(5, 1); + internal[5] += 1; + check_segtree(&internal, &mut segtree); + + segtree.set(6, 0); + internal[6] = 0; + check_segtree(&internal, &mut segtree); + + segtree.apply_range(3, 8, 2); + internal[3..8].iter_mut().for_each(|e| *e += 2); + check_segtree(&internal, &mut segtree); + } + + //noinspection DuplicatedCode + fn check_segtree(base: &[i32], segtree: &mut LazySegtree) { + let n = base.len(); + #[allow(clippy::needless_range_loop)] + for i in 0..n { + assert_eq!(segtree.get(i), base[i]); + } + for i in 0..=n { + for j in i..=n { + assert_eq!( + segtree.prod(i, j), + base[i..j].iter().max().copied().unwrap_or(i32::min_value()) + ); + } + } + assert_eq!( + segtree.all_prod(), + base.iter().max().copied().unwrap_or(i32::min_value()) + ); + for k in 0..=10 { + let f = |x| x < k; + for i in 0..=n { + assert_eq!( + Some(segtree.max_right(i, f)), + (i..=n) + .filter(|&j| f(base[i..j] + .iter() + .max() + .copied() + .unwrap_or(i32::min_value()))) + .max() + ); + } + for j in 0..=n { + assert_eq!( + Some(segtree.min_left(j, f)), + (0..=j) + .filter(|&i| f(base[i..j] + .iter() + .max() + .copied() + .unwrap_or(i32::min_value()))) + .min() + ); + } + } + } +} diff --git a/src/segtree.rs b/src/segtree.rs index e11c417..744f4c5 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -224,6 +224,7 @@ mod test { check_segtree(&internal, &segtree); } + //noinspection DuplicatedCode fn check_segtree(base: &[i32], segtree: &Segtree>) { let n = base.len(); #[allow(clippy::needless_range_loop)] From 93a290636c4cb05ef5b199b503c1205f9d478676 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 17:14:19 +0900 Subject: [PATCH 16/27] Follow naming convension (mod test -> tests) --- src/segtree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segtree.rs b/src/segtree.rs index e11c417..901ee95 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -196,7 +196,7 @@ where } #[cfg(test)] -mod test { +mod tests { use crate::segtree::Max; use crate::Segtree; From 51dd0db6cd0c36b1ba542cb973d842b3fd8e8713 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 21:17:42 +0900 Subject: [PATCH 17/27] Implement Debug for LazySegtree --- src/lazysegtree.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/lazysegtree.rs b/src/lazysegtree.rs index 1934ea2..8878576 100644 --- a/src/lazysegtree.rs +++ b/src/lazysegtree.rs @@ -286,6 +286,32 @@ where } } +// TODO is it useful? +use std::fmt::{Debug, Error, Formatter, Write}; +impl Debug for LazySegtree +where + F: MapMonoid, + F::F: Debug, + ::S: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + for i in 0..self.log { + for j in 0..1 << i { + f.write_fmt(format_args!( + "{:?}[{:?}]\t", + self.d[(1 << i) + j], + self.lz[(1 << i) + j] + ))?; + } + f.write_char('\n')?; + } + for i in 0..self.size { + f.write_fmt(format_args!("{:?}\t", self.d[self.size + i]))?; + } + Ok(()) + } +} + #[cfg(test)] mod tests { use crate::{LazySegtree, MapMonoid, Max}; From 4878021e015e292cc2bc077c67b14f2359d1a9ad Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 21:18:00 +0900 Subject: [PATCH 18/27] Added example for Practice2-K --- .../practice2_k_range_affine_range_sum.rs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 examples/practice2_k_range_affine_range_sum.rs diff --git a/examples/practice2_k_range_affine_range_sum.rs b/examples/practice2_k_range_affine_range_sum.rs new file mode 100644 index 0000000..72995f4 --- /dev/null +++ b/examples/practice2_k_range_affine_range_sum.rs @@ -0,0 +1,67 @@ +use ac_library_rs::{LazySegtree, MapMonoid, ModInt998244353, Monoid}; +use std::io::Read; + +type Mint = ModInt998244353; +struct Sum; +impl Monoid for Sum { + type S = (Mint, usize); + + fn identity() -> Self::S { + (0.into(), 0) + } + + fn binary_operation((a, n): Self::S, (b, m): Self::S) -> Self::S { + (a + b, n + m) + } +} +struct Affine; +impl MapMonoid for Affine { + type M = Sum; + type F = (Mint, Mint); + + fn identity_map() -> Self::F { + (1.into(), 0.into()) + } + + fn mapping((a, b): Self::F, (x, n): ::S) -> ::S { + (a * x + b * Mint::new(n), n) + } + + // a(cx + d) + b = (ac)x + (ad+b) + fn composition((a, b): Self::F, (c, d): Self::F) -> Self::F { + (a * c, a * d + b) + } +} + +#[allow(clippy::many_single_char_names)] +fn main() { + let mut buf = String::new(); + std::io::stdin().read_to_string(&mut buf).unwrap(); + let mut input = buf.split_whitespace(); + + let n = input.next().unwrap().parse().unwrap(); + let q = input.next().unwrap().parse().unwrap(); + let mut segtree: LazySegtree = input + .by_ref() + .take(n) + .map(|s| (s.parse().unwrap(), 1)) + .collect::>() + .into(); + for _ in 0..q { + match input.next().unwrap().parse().unwrap() { + 0 => { + let l = input.next().unwrap().parse().unwrap(); + let r = input.next().unwrap().parse().unwrap(); + let b = input.next().unwrap().parse().unwrap(); + let c = input.next().unwrap().parse().unwrap(); + segtree.apply_range(l, r, (b, c)); + } + 1 => { + let l = input.next().unwrap().parse().unwrap(); + let r = input.next().unwrap().parse().unwrap(); + println!("{}", segtree.prod(l, r).0); + } + _ => {} + } + } +} From 707b56df1a19d0c6346d8ada6349db527957d217 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 21:52:43 +0900 Subject: [PATCH 19/27] Added example for Practice2-L --- examples/practice2_l_lazy_segment_tree.rs | 63 +++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 examples/practice2_l_lazy_segment_tree.rs diff --git a/examples/practice2_l_lazy_segment_tree.rs b/examples/practice2_l_lazy_segment_tree.rs new file mode 100644 index 0000000..6d9a0a9 --- /dev/null +++ b/examples/practice2_l_lazy_segment_tree.rs @@ -0,0 +1,63 @@ +#![allow(clippy::many_single_char_names)] +use ac_library_rs::{LazySegtree, MapMonoid, Monoid}; +use std::io::Read; +use std::iter; + +struct M; +impl Monoid for M { + type S = (u64, u64, u64); + fn identity() -> Self::S { + (0, 0, 0) + } + fn binary_operation((a, b, c): Self::S, (d, e, f): Self::S) -> Self::S { + (a + d, b + e, c + f + b * d) + } +} +struct F; +impl MapMonoid for F { + type M = M; + type F = bool; + + fn identity_map() -> Self::F { + false + } + fn mapping(f: Self::F, (a, b, c): ::S) -> ::S { + if f { + // (a + b) * (a + b - 1) / 2 - a * (a - 1) / 2 - b * (b - 1) / 2 - c + // = a * b - c + (b, a, a * b - c) + } else { + (a, b, c) + } + } + fn composition(f: Self::F, g: Self::F) -> Self::F { + f ^ g + } +} + +fn main() { + let mut buf = String::new(); + std::io::stdin().read_to_string(&mut buf).unwrap(); + let mut input = buf.split_whitespace(); + + let n = input.next().unwrap().parse().unwrap(); + let q = input.next().unwrap().parse().unwrap(); + let mut segtree: LazySegtree = iter::once((0, 0, 0)) + .chain(input.by_ref().take(n).map(|s| match s { + "0" => (1, 0, 0), + "1" => (0, 1, 0), + _ => panic!(), + })) + .collect::>() + .into(); + for _ in 0..q { + let t = input.next().unwrap().parse().unwrap(); + let l = input.next().unwrap().parse().unwrap(); + let r: usize = input.next().unwrap().parse().unwrap(); + match t { + 1 => segtree.apply_range(l, r + 1, true), + 2 => println!("{}", segtree.prod(l, r + 1).2), + _ => {} + } + } +} From 3a43da60564e9ff9444343c87cf22919bb69618b Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sat, 12 Sep 2020 21:57:19 +0900 Subject: [PATCH 20/27] Change position of newline --- src/segtree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segtree.rs b/src/segtree.rs index 901ee95..7315c5e 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -9,8 +9,8 @@ pub trait Monoid { fn identity() -> Self::S; fn binary_operation(a: Self::S, b: Self::S) -> Self::S; } -pub struct Max(PhantomData S>); +pub struct Max(PhantomData S>); // TODO We should not restrict to integral impl Monoid for Max where From ce40d2a1c95b46e3a738e14dc0dcaa86359aa540 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Sun, 13 Sep 2020 13:42:44 +0900 Subject: [PATCH 21/27] Apply the change that I forgot --- examples/practice2_j_segment_tree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/practice2_j_segment_tree.rs b/examples/practice2_j_segment_tree.rs index 961efc8..05c2afe 100644 --- a/examples/practice2_j_segment_tree.rs +++ b/examples/practice2_j_segment_tree.rs @@ -8,7 +8,7 @@ fn main() { let n: usize = input.next().unwrap().parse().unwrap(); let q: usize = input.next().unwrap().parse().unwrap(); - let mut segtree = Segtree::>::new(n + 1); + let mut segtree = Segtree::>::new(n + 1); for i in 1..=n { segtree.set(i, input.next().unwrap().parse().unwrap()); } From d51a67bd7f2f34096bc80ae24f30f67f4a8ebb8b Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Mon, 14 Sep 2020 23:15:51 +0900 Subject: [PATCH 22/27] Split integral traits into four subtraits --- src/internal_type_traits.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/internal_type_traits.rs b/src/internal_type_traits.rs index 73ba2e6..88a52a9 100644 --- a/src/internal_type_traits.rs +++ b/src/internal_type_traits.rs @@ -52,37 +52,65 @@ pub trait Integral: + fmt::Debug + fmt::Binary + fmt::Octal + + Zero + + One + + BoundedBelow + + BoundedAbove { +} + +/// Class that has additive identity element +pub trait Zero { + /// The additive identity element fn zero() -> Self; +} + +/// Class that has multiplicative identity element +pub trait One { + /// The multiplicative identity element fn one() -> Self; +} + +pub trait BoundedBelow { fn min_value() -> Self; +} + +pub trait BoundedAbove { fn max_value() -> Self; } macro_rules! impl_integral { ($($ty:ty),*) => { $( - impl Integral for $ty { + impl Zero for $ty { #[inline] fn zero() -> Self { 0 } + } + impl One for $ty { #[inline] fn one() -> Self { 1 } + } + impl BoundedBelow for $ty { #[inline] fn min_value() -> Self { Self::min_value() } + } + impl BoundedAbove for $ty { #[inline] fn max_value() -> Self { Self::max_value() } } + + impl Integral for $ty {} )* }; } From 5650b8802e40bc028ff96cc3a8d5d937b4e978a3 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Tue, 15 Sep 2020 00:00:53 +0900 Subject: [PATCH 23/27] Modify binary_operation and add some traits * Changed the signature of binary_operation so that it takes references * Added some default Monoid implementation --- src/segtree.rs | 79 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/src/segtree.rs b/src/segtree.rs index 7315c5e..f8397a2 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -1,29 +1,70 @@ use crate::internal_bit::ceil_pow2; -use crate::internal_type_traits::Integral; -use std::cmp::max; +use crate::internal_type_traits::{BoundedAbove, BoundedBelow, One, Zero}; +use std::cmp::{max, min}; +use std::convert::Infallible; use std::marker::PhantomData; +use std::ops::{Add, Mul}; // TODO Should I split monoid-related traits to another module? pub trait Monoid { type S: Clone; fn identity() -> Self::S; - fn binary_operation(a: Self::S, b: Self::S) -> Self::S; + fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S; } -pub struct Max(PhantomData S>); -// TODO We should not restrict to integral +pub struct Max(Infallible, PhantomData S>); impl Monoid for Max where - S: Integral, + S: Copy + Ord + BoundedBelow, { type S = S; - fn identity() -> Self::S { S::min_value() } + fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { + max(*a, *b) + } +} + +pub struct Min(Infallible, PhantomData S>); +impl Monoid for Min +where + S: Copy + Ord + BoundedAbove, +{ + type S = S; + fn identity() -> Self::S { + S::max_value() + } + fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { + min(*a, *b) + } +} + +pub struct Sum(Infallible, PhantomData S>); +impl Monoid for Sum +where + S: Copy + Add + Zero, +{ + type S = S; + fn identity() -> Self::S { + S::zero() + } + fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { + *a + *b + } +} - fn binary_operation(a: Self::S, b: Self::S) -> Self::S { - max(a, b) +pub struct Product(Infallible, PhantomData S>); +impl Monoid for Product +where + S: Copy + Mul + One, +{ + type S = S; + fn identity() -> Self::S { + S::one() + } + fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { + *a * *b } } @@ -75,18 +116,18 @@ impl Segtree { while l < r { if l & 1 != 0 { - sml = M::binary_operation(sml, self.d[l].clone()); + sml = M::binary_operation(&sml, &self.d[l]); l += 1; } if r & 1 != 0 { r -= 1; - smr = M::binary_operation(self.d[r].clone(), smr); + smr = M::binary_operation(&self.d[r], &smr); } l >>= 1; r >>= 1; } - M::binary_operation(sml, smr) + M::binary_operation(&sml, &smr) } pub fn all_prod(&self) -> M::S { @@ -109,10 +150,10 @@ impl Segtree { while l % 2 == 0 { l >>= 1; } - if !f(M::binary_operation(sm.clone(), self.d[l].clone())) { + if !f(M::binary_operation(&sm, &self.d[l])) { while l < self.size { l *= 2; - let res = M::binary_operation(sm.clone(), self.d[l].clone()); + let res = M::binary_operation(&sm, &self.d[l]); if f(res.clone()) { sm = res; l += 1; @@ -120,7 +161,7 @@ impl Segtree { } return l - self.size; } - sm = M::binary_operation(sm.clone(), self.d[l].clone()); + sm = M::binary_operation(&sm, &self.d[l]); l += 1; // while { @@ -148,10 +189,10 @@ impl Segtree { while r > 1 && r % 2 == 1 { r >>= 1; } - if !f(M::binary_operation(self.d[r].clone(), sm.clone())) { + if !f(M::binary_operation(&self.d[r], &sm)) { while r < self.size { r = 2 * r + 1; - let res = M::binary_operation(self.d[r].clone(), sm.clone()); + let res = M::binary_operation(&self.d[r], &sm); if f(res.clone()) { sm = res; r -= 1; @@ -159,7 +200,7 @@ impl Segtree { } return r + 1 - self.size; } - sm = M::binary_operation(self.d[r].clone(), sm.clone()); + sm = M::binary_operation(&self.d[r], &sm); // while { let r = r as isize; @@ -170,7 +211,7 @@ impl Segtree { } fn update(&mut self, k: usize) { - self.d[k] = M::binary_operation(self.d[2 * k].clone(), self.d[2 * k + 1].clone()); + self.d[k] = M::binary_operation(&self.d[2 * k], &self.d[2 * k + 1]); } } From 32dbc68fb6af6ac444299db93b38a1c4e3fe56ae Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Tue, 15 Sep 2020 00:01:37 +0900 Subject: [PATCH 24/27] cargo fmt --- src/segtree.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/segtree.rs b/src/segtree.rs index f8397a2..378a0b3 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -43,7 +43,7 @@ where pub struct Sum(Infallible, PhantomData S>); impl Monoid for Sum where - S: Copy + Add + Zero, + S: Copy + Add + Zero, { type S = S; fn identity() -> Self::S { @@ -57,7 +57,7 @@ where pub struct Product(Infallible, PhantomData S>); impl Monoid for Product where - S: Copy + Mul + One, + S: Copy + Mul + One, { type S = S; fn identity() -> Self::S { From f54acaf2ec061affd813d86013c473ee83b03a54 Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Tue, 15 Sep 2020 00:15:47 +0900 Subject: [PATCH 25/27] Change arguments from value to reference --- .../practice2_k_range_affine_range_sum.rs | 6 +-- examples/practice2_l_lazy_segment_tree.rs | 6 +-- src/lazysegtree.rs | 38 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/practice2_k_range_affine_range_sum.rs b/examples/practice2_k_range_affine_range_sum.rs index 72995f4..e07c542 100644 --- a/examples/practice2_k_range_affine_range_sum.rs +++ b/examples/practice2_k_range_affine_range_sum.rs @@ -10,7 +10,7 @@ impl Monoid for Sum { (0.into(), 0) } - fn binary_operation((a, n): Self::S, (b, m): Self::S) -> Self::S { + fn binary_operation(&(a, n): &Self::S, &(b, m): &Self::S) -> Self::S { (a + b, n + m) } } @@ -23,12 +23,12 @@ impl MapMonoid for Affine { (1.into(), 0.into()) } - fn mapping((a, b): Self::F, (x, n): ::S) -> ::S { + fn mapping(&(a, b): &Self::F, &(x, n): &::S) -> ::S { (a * x + b * Mint::new(n), n) } // a(cx + d) + b = (ac)x + (ad+b) - fn composition((a, b): Self::F, (c, d): Self::F) -> Self::F { + fn composition(&(a, b): &Self::F, &(c, d): &Self::F) -> Self::F { (a * c, a * d + b) } } diff --git a/examples/practice2_l_lazy_segment_tree.rs b/examples/practice2_l_lazy_segment_tree.rs index 6d9a0a9..61469d4 100644 --- a/examples/practice2_l_lazy_segment_tree.rs +++ b/examples/practice2_l_lazy_segment_tree.rs @@ -9,7 +9,7 @@ impl Monoid for M { fn identity() -> Self::S { (0, 0, 0) } - fn binary_operation((a, b, c): Self::S, (d, e, f): Self::S) -> Self::S { + fn binary_operation(&(a, b, c): &Self::S, &(d, e, f): &Self::S) -> Self::S { (a + d, b + e, c + f + b * d) } } @@ -21,7 +21,7 @@ impl MapMonoid for F { fn identity_map() -> Self::F { false } - fn mapping(f: Self::F, (a, b, c): ::S) -> ::S { + fn mapping(&f: &Self::F, &(a, b, c): &::S) -> ::S { if f { // (a + b) * (a + b - 1) / 2 - a * (a - 1) / 2 - b * (b - 1) / 2 - c // = a * b - c @@ -30,7 +30,7 @@ impl MapMonoid for F { (a, b, c) } } - fn composition(f: Self::F, g: Self::F) -> Self::F { + fn composition(&f: &Self::F, &g: &Self::F) -> Self::F { f ^ g } } diff --git a/src/lazysegtree.rs b/src/lazysegtree.rs index 8878576..47020a8 100644 --- a/src/lazysegtree.rs +++ b/src/lazysegtree.rs @@ -9,14 +9,14 @@ pub trait MapMonoid { Self::M::identity() } fn binary_operation( - a: ::S, - b: ::S, + a: &::S, + b: &::S, ) -> ::S { Self::M::binary_operation(a, b) } fn identity_map() -> Self::F; - fn mapping(f: Self::F, x: ::S) -> ::S; - fn composition(f: Self::F, g: Self::F) -> Self::F; + fn mapping(f: &Self::F, x: &::S) -> ::S; + fn composition(f: &Self::F, g: &Self::F) -> Self::F; } impl Default for LazySegtree { @@ -95,18 +95,18 @@ impl LazySegtree { let mut smr = F::identity_element(); while l < r { if l & 1 != 0 { - sml = F::binary_operation(sml, self.d[l].clone()); + sml = F::binary_operation(&sml, &self.d[l]); l += 1; } if r & 1 != 0 { r -= 1; - smr = F::binary_operation(self.d[r].clone(), smr); + smr = F::binary_operation(&self.d[r], &smr); } l >>= 1; r >>= 1; } - F::binary_operation(sml, smr) + F::binary_operation(&sml, &smr) } pub fn all_prod(&self) -> ::S { @@ -119,7 +119,7 @@ impl LazySegtree { for i in (1..=self.log).rev() { self.push(p >> i); } - self.d[p] = F::mapping(f, self.d[p].clone()); + self.d[p] = F::mapping(&f, &self.d[p]); for i in 1..=self.log { self.update(p >> i); } @@ -190,11 +190,11 @@ impl LazySegtree { while l % 2 == 0 { l >>= 1; } - if !g(F::binary_operation(sm.clone(), self.d[l].clone())) { + if !g(F::binary_operation(&sm, &self.d[l])) { while l < self.size { self.push(l); l *= 2; - let res = F::binary_operation(sm.clone(), self.d[l].clone()); + let res = F::binary_operation(&sm, &self.d[l]); if g(res.clone()) { sm = res; l += 1; @@ -202,7 +202,7 @@ impl LazySegtree { } return l - self.size; } - sm = F::binary_operation(sm, self.d[l].clone()); + sm = F::binary_operation(&sm, &self.d[l]); l += 1; //while { @@ -233,11 +233,11 @@ impl LazySegtree { while r > 1 && r % 2 != 0 { r >>= 1; } - if !g(F::binary_operation(self.d[r].clone(), sm.clone())) { + if !g(F::binary_operation(&self.d[r], &sm)) { while r < self.size { self.push(r); r = 2 * r + 1; - let res = F::binary_operation(self.d[r].clone(), sm.clone()); + let res = F::binary_operation(&self.d[r], &sm); if g(res.clone()) { sm = res; r -= 1; @@ -245,7 +245,7 @@ impl LazySegtree { } return r + 1 - self.size; } - sm = F::binary_operation(self.d[r].clone(), sm); + sm = F::binary_operation(&self.d[r], &sm); // while { let r = r as isize; @@ -271,12 +271,12 @@ where F: MapMonoid, { fn update(&mut self, k: usize) { - self.d[k] = F::binary_operation(self.d[2 * k].clone(), self.d[2 * k + 1].clone()); + self.d[k] = F::binary_operation(&self.d[2 * k], &self.d[2 * k + 1]); } fn all_apply(&mut self, k: usize, f: F::F) { - self.d[k] = F::mapping(f.clone(), self.d[k].clone()); + self.d[k] = F::mapping(&f, &self.d[k]); if k < self.size { - self.lz[k] = F::composition(f, self.lz[k].clone()); + self.lz[k] = F::composition(&f, &self.lz[k]); } } fn push(&mut self, k: usize) { @@ -325,11 +325,11 @@ mod tests { 0 } - fn mapping(f: i32, x: i32) -> i32 { + fn mapping(&f: &i32, &x: &i32) -> i32 { f + x } - fn composition(f: i32, g: i32) -> i32 { + fn composition(&f: &i32, &g: &i32) -> i32 { f + g } } From 48ceeb637556fba0564f46ae0e2fe9952257b21c Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Tue, 15 Sep 2020 00:55:25 +0900 Subject: [PATCH 26/27] Changed the signature of f in max_right & min_left --- examples/practice2_j_segment_tree.rs | 2 +- src/segtree.rs | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/practice2_j_segment_tree.rs b/examples/practice2_j_segment_tree.rs index 05c2afe..ed5d043 100644 --- a/examples/practice2_j_segment_tree.rs +++ b/examples/practice2_j_segment_tree.rs @@ -27,7 +27,7 @@ fn main() { 3 => { let x = input.next().unwrap().parse().unwrap(); let v = input.next().unwrap().parse().unwrap(); - println!("{}", segtree.max_right(x, |a| a < v)) + println!("{}", segtree.max_right(x, |a| a < &v)) } _ => {} } diff --git a/src/segtree.rs b/src/segtree.rs index 378a0b3..68c0ccc 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -136,10 +136,10 @@ impl Segtree { pub fn max_right(&self, mut l: usize, f: F) -> usize where - F: Fn(M::S) -> bool, + F: Fn(&M::S) -> bool, { assert!(l <= self.n); - assert!(f(M::identity())); + assert!(f(&M::identity())); if l == self.n { return self.n; } @@ -150,11 +150,11 @@ impl Segtree { while l % 2 == 0 { l >>= 1; } - if !f(M::binary_operation(&sm, &self.d[l])) { + if !f(&M::binary_operation(&sm, &self.d[l])) { while l < self.size { l *= 2; let res = M::binary_operation(&sm, &self.d[l]); - if f(res.clone()) { + if f(&res) { sm = res; l += 1; } @@ -174,10 +174,10 @@ impl Segtree { pub fn min_left(&self, mut r: usize, f: F) -> usize where - F: Fn(M::S) -> bool, + F: Fn(&M::S) -> bool, { assert!(r <= self.n); - assert!(f(M::identity())); + assert!(f(&M::identity())); if r == 0 { return 0; } @@ -189,11 +189,11 @@ impl Segtree { while r > 1 && r % 2 == 1 { r >>= 1; } - if !f(M::binary_operation(&self.d[r], &sm)) { + if !f(&M::binary_operation(&self.d[r], &sm)) { while r < self.size { r = 2 * r + 1; let res = M::binary_operation(&self.d[r], &sm); - if f(res.clone()) { + if f(&res) { sm = res; r -= 1; } @@ -284,12 +284,12 @@ mod tests { base.iter().max().copied().unwrap_or(i32::min_value()) ); for k in 0..=10 { - let f = |x| x < k; + let f = |&x: &i32| x < k; for i in 0..=n { assert_eq!( Some(segtree.max_right(i, f)), (i..=n) - .filter(|&j| f(base[i..j] + .filter(|&j| f(&base[i..j] .iter() .max() .copied() @@ -301,7 +301,7 @@ mod tests { assert_eq!( Some(segtree.min_left(j, f)), (0..=j) - .filter(|&i| f(base[i..j] + .filter(|&i| f(&base[i..j] .iter() .max() .copied() From d4bb776e38ceb0199d9f7d7e00a8c837f8696a3a Mon Sep 17 00:00:00 2001 From: TonalidadeHidrica <47710717+TonalidadeHidrica@users.noreply.github.com> Date: Tue, 15 Sep 2020 16:39:37 +0900 Subject: [PATCH 27/27] Changed the monoid namme --- src/lib.rs | 2 +- src/segtree.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0b5a619..fba745a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,7 +28,7 @@ pub use modint::{ ModInt998244353, Modulus, RemEuclidU32, StaticModInt, }; pub use scc::SccGraph; -pub use segtree::{Max, Monoid, Segtree}; +pub use segtree::{Additive, Max, Min, Monoid, Multiplicative, Segtree}; pub use string::{ lcp_array, lcp_array_arbitrary, suffix_array, suffix_array_arbitrary, suffix_array_manual, z_algorithm, z_algorithm_arbitrary, diff --git a/src/segtree.rs b/src/segtree.rs index 68c0ccc..2265ff1 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -40,8 +40,8 @@ where } } -pub struct Sum(Infallible, PhantomData S>); -impl Monoid for Sum +pub struct Additive(Infallible, PhantomData S>); +impl Monoid for Additive where S: Copy + Add + Zero, { @@ -54,8 +54,8 @@ where } } -pub struct Product(Infallible, PhantomData S>); -impl Monoid for Product +pub struct Multiplicative(Infallible, PhantomData S>); +impl Monoid for Multiplicative where S: Copy + Mul + One, {