@@ -73,7 +73,27 @@ impl<F: MapMonoid> LazySegtree<F> {
7373 self . d [ p] . clone ( )
7474 }
7575
76- pub fn prod ( & mut self , mut l : usize , mut r : usize ) -> <F :: M as Monoid >:: S {
76+ pub fn prod < R > ( & mut self , range : R ) -> <F :: M as Monoid >:: S
77+ where
78+ R : RangeBounds < usize > ,
79+ {
80+ // Trivial optimization
81+ if range. start_bound ( ) == Bound :: Unbounded && range. end_bound ( ) == Bound :: Unbounded {
82+ return self . all_prod ( ) ;
83+ }
84+
85+ let mut r = match range. end_bound ( ) {
86+ Bound :: Included ( r) => r + 1 ,
87+ Bound :: Excluded ( r) => * r,
88+ Bound :: Unbounded => self . n ,
89+ } ;
90+ let mut l = match range. start_bound ( ) {
91+ Bound :: Included ( l) => * l,
92+ Bound :: Excluded ( l) => l + 1 ,
93+ // TODO: There are another way of optimizing [0..r)
94+ Bound :: Unbounded => 0 ,
95+ } ;
96+
7797 assert ! ( l <= r && r <= self . n) ;
7898 if l == r {
7999 return F :: identity_element ( ) ;
@@ -124,7 +144,22 @@ impl<F: MapMonoid> LazySegtree<F> {
124144 self . update ( p >> i) ;
125145 }
126146 }
127- pub fn apply_range ( & mut self , mut l : usize , mut r : usize , f : F :: F ) {
147+ pub fn apply_range < R > ( & mut self , range : R , f : F :: F )
148+ where
149+ R : RangeBounds < usize > ,
150+ {
151+ let mut r = match range. end_bound ( ) {
152+ Bound :: Included ( r) => r + 1 ,
153+ Bound :: Excluded ( r) => * r,
154+ Bound :: Unbounded => self . n ,
155+ } ;
156+ let mut l = match range. start_bound ( ) {
157+ Bound :: Included ( l) => * l,
158+ Bound :: Excluded ( l) => l + 1 ,
159+ // TODO: There are another way of optimizing [0..r)
160+ Bound :: Unbounded => 0 ,
161+ } ;
162+
128163 assert ! ( l <= r && r <= self . n) ;
129164 if l == r {
130165 return ;
@@ -287,7 +322,10 @@ where
287322}
288323
289324// TODO is it useful?
290- use std:: fmt:: { Debug , Error , Formatter , Write } ;
325+ use std:: {
326+ fmt:: { Debug , Error , Formatter , Write } ,
327+ ops:: { Bound , RangeBounds } ,
328+ } ;
291329impl < F > Debug for LazySegtree < F >
292330where
293331 F : MapMonoid ,
@@ -314,6 +352,8 @@ where
314352
315353#[ cfg( test) ]
316354mod tests {
355+ use std:: ops:: { Bound :: * , RangeBounds } ;
356+
317357 use crate :: { LazySegtree , MapMonoid , Max } ;
318358
319359 struct MaxAdd ;
@@ -361,9 +401,13 @@ mod tests {
361401 internal[ 6 ] = 0 ;
362402 check_segtree ( & internal, & mut segtree) ;
363403
364- segtree. apply_range ( 3 , 8 , 2 ) ;
404+ segtree. apply_range ( 3 .. 8 , 2 ) ;
365405 internal[ 3 ..8 ] . iter_mut ( ) . for_each ( |e| * e += 2 ) ;
366406 check_segtree ( & internal, & mut segtree) ;
407+
408+ segtree. apply_range ( 2 ..=5 , 7 ) ;
409+ internal[ 2 ..=5 ] . iter_mut ( ) . for_each ( |e| * e += 7 ) ;
410+ check_segtree ( & internal, & mut segtree) ;
367411 }
368412
369413 //noinspection DuplicatedCode
@@ -373,12 +417,20 @@ mod tests {
373417 for i in 0 ..n {
374418 assert_eq ! ( segtree. get( i) , base[ i] ) ;
375419 }
420+
421+ check ( base, segtree, ..) ;
376422 for i in 0 ..=n {
423+ check ( base, segtree, ..i) ;
424+ check ( base, segtree, i..) ;
425+ if i < n {
426+ check ( base, segtree, ..=i) ;
427+ }
377428 for j in i..=n {
378- assert_eq ! (
379- segtree. prod( i, j) ,
380- base[ i..j] . iter( ) . max( ) . copied( ) . unwrap_or( i32 :: min_value( ) )
381- ) ;
429+ check ( base, segtree, i..j) ;
430+ if j < n {
431+ check ( base, segtree, i..=j) ;
432+ check ( base, segtree, ( Excluded ( i) , Included ( j) ) ) ;
433+ }
382434 }
383435 }
384436 assert_eq ! (
@@ -413,4 +465,15 @@ mod tests {
413465 }
414466 }
415467 }
468+
469+ fn check ( base : & [ i32 ] , segtree : & mut LazySegtree < MaxAdd > , range : impl RangeBounds < usize > ) {
470+ let expected = base
471+ . iter ( )
472+ . enumerate ( )
473+ . filter_map ( |( i, a) | Some ( a) . filter ( |_| range. contains ( & i) ) )
474+ . max ( )
475+ . copied ( )
476+ . unwrap_or ( i32:: min_value ( ) ) ;
477+ assert_eq ! ( segtree. prod( range) , expected) ;
478+ }
416479}
0 commit comments