1+ /**
2+ * TODO: verify {@link LazySegTree#maxRight} and {@link LazySegTree#minLeft}
3+ *
4+ * @verified https://atcoder.jp/contests/practice2/tasks/practice2_k
5+ */
6+ class LazySegTree <S , F > {
7+ final int MAX ;
8+
9+ final int N ;
10+ final int Log ;
11+ final java .util .function .BinaryOperator <S > Op ;
12+ final S E ;
13+ final java .util .function .BiFunction <F , S , S > Mapping ;
14+ final java .util .function .BinaryOperator <F > Composition ;
15+ final F Id ;
16+
17+ final S [] Dat ;
18+ final F [] Laz ;
19+
20+ @ SuppressWarnings ("unchecked" )
21+ public LazySegTree (int n , java .util .function .BinaryOperator <S > op , S e , java .util .function .BiFunction <F , S , S > mapping , java .util .function .BinaryOperator <F > composition , F id ) {
22+ this .MAX = n ;
23+ int k = 1 ;
24+ while (k < n ) k <<= 1 ;
25+ this .N = k ;
26+ this .Log = Integer .numberOfTrailingZeros (N );
27+ this .Op = op ;
28+ this .E = e ;
29+ this .Mapping = mapping ;
30+ this .Composition = composition ;
31+ this .Id = id ;
32+ this .Dat = (S []) new Object [N << 1 ];
33+ this .Laz = (F []) new Object [N ];
34+ java .util .Arrays .fill (Dat , E );
35+ java .util .Arrays .fill (Laz , Id );
36+ }
37+
38+ public LazySegTree (S [] dat , java .util .function .BinaryOperator <S > op , S e , java .util .function .BiFunction <F , S , S > mapping , java .util .function .BinaryOperator <F > composition , F id ) {
39+ this (dat .length , op , e , mapping , composition , id );
40+ build (dat );
41+ }
42+
43+ private void build (S [] dat ) {
44+ int l = dat .length ;
45+ System .arraycopy (dat , 0 , Dat , N , l );
46+ for (int i = N - 1 ; i > 0 ; i --) {
47+ Dat [i ] = Op .apply (Dat [i << 1 | 0 ], Dat [i << 1 | 1 ]);
48+ }
49+ }
50+
51+ private void push (int k ) {
52+ if (Laz [k ] == Id ) return ;
53+ int lk = k << 1 | 0 , rk = k << 1 | 1 ;
54+ Dat [lk ] = Mapping .apply (Laz [k ], Dat [lk ]);
55+ Dat [rk ] = Mapping .apply (Laz [k ], Dat [rk ]);
56+ if (lk < N ) Laz [lk ] = Composition .apply (Laz [k ], Laz [lk ]);
57+ if (rk < N ) Laz [rk ] = Composition .apply (Laz [k ], Laz [rk ]);
58+ Laz [k ] = Id ;
59+ }
60+
61+ private void pushTo (int k ) {
62+ for (int i = Log ; i > 0 ; i --) push (k >> i );
63+ }
64+
65+ private void pushTo (int lk , int rk ) {
66+ for (int i = Log ; i > 0 ; i --) {
67+ if (((lk >> i ) << i ) != lk ) push (lk >> i );
68+ if (((rk >> i ) << i ) != rk ) push (rk >> i );
69+ }
70+ }
71+
72+ private void updateFrom (int k ) {
73+ k >>= 1 ;
74+ while (k > 0 ) {
75+ Dat [k ] = Op .apply (Dat [k << 1 | 0 ], Dat [k << 1 | 1 ]);
76+ k >>= 1 ;
77+ }
78+ }
79+
80+ private void updateFrom (int lk , int rk ) {
81+ for (int i = 1 ; i <= Log ; i ++) {
82+ if (((lk >> i ) << i ) != lk ) {
83+ int lki = lk >> i ;
84+ Dat [lki ] = Op .apply (Dat [lki << 1 | 0 ], Dat [lki << 1 | 1 ]);
85+ }
86+ if (((rk >> i ) << i ) != rk ) {
87+ int rki = (rk - 1 ) >> i ;
88+ Dat [rki ] = Op .apply (Dat [rki << 1 | 0 ], Dat [rki << 1 | 1 ]);
89+ }
90+ }
91+ }
92+
93+ public void set (int p , S x ) {
94+ exclusiveRangeCheck (p );
95+ p += N ;
96+ pushTo (p );
97+ Dat [p ] = x ;
98+ updateFrom (p );
99+ }
100+
101+ public S get (int p ) {
102+ exclusiveRangeCheck (p );
103+ p += N ;
104+ pushTo (p );
105+ return Dat [p ];
106+ }
107+
108+ public S prod (int l , int r ) {
109+ if (l > r ) {
110+ throw new IllegalArgumentException (
111+ String .format ("Invalid range: [%d, %d)" , l , r )
112+ );
113+ }
114+ inclusiveRangeCheck (l );
115+ inclusiveRangeCheck (r );
116+ if (l == r ) return E ;
117+ l += N ; r += N ;
118+ pushTo (l , r );
119+ S sumLeft = E , sumRight = E ;
120+ while (l < r ) {
121+ if ((l & 1 ) == 1 ) sumLeft = Op .apply (sumLeft , Dat [l ++]);
122+ if ((r & 1 ) == 1 ) sumRight = Op .apply (Dat [--r ], sumRight );
123+ l >>= 1 ; r >>= 1 ;
124+ }
125+ return Op .apply (sumLeft , sumRight );
126+ }
127+
128+ public S allProd () {
129+ return Dat [1 ];
130+ }
131+
132+ public void apply (int p , F f ) {
133+ Dat [p ] = Mapping .apply (f , get (p ));
134+ updateFrom (p + N );
135+ }
136+
137+ public void apply (int l , int r , F f ) {
138+ if (l > r ) {
139+ throw new IllegalArgumentException (
140+ String .format ("Invalid range: [%d, %d)" , l , r )
141+ );
142+ }
143+ inclusiveRangeCheck (l );
144+ inclusiveRangeCheck (r );
145+ if (l == r ) return ;
146+ l += N ; r += N ;
147+ pushTo (l , r );
148+ for (int l2 = l , r2 = r ; l2 < r2 ;) {
149+ if ((l2 & 1 ) == 1 ) {
150+ Dat [l2 ] = Mapping .apply (f , Dat [l2 ]);
151+ if (l2 < N ) Laz [l2 ] = Composition .apply (f , Laz [l2 ]);
152+ l2 ++;
153+ }
154+ if ((r2 & 1 ) == 1 ) {
155+ r2 --;
156+ Dat [r2 ] = Mapping .apply (f , Dat [r2 ]);
157+ if (r2 < N ) Laz [r2 ] = Composition .apply (f , Laz [r2 ]);
158+ }
159+ l2 >>= 1 ; r2 >>= 1 ;
160+ }
161+ updateFrom (l , r );
162+ }
163+
164+ public int maxRight (int l , java .util .function .Predicate <S > g ) {
165+ inclusiveRangeCheck (l );
166+ if (!f .test (E )) {
167+ throw new IllegalArgumentException ("Identity element must satisfy the condition." );
168+ }
169+ if (l == MAX ) return MAX ;
170+ l += N ;
171+ pushTo (l );
172+ S sum = E ;
173+ do {
174+ l >>= Integer .numberOfTrailingZeros (l );
175+ if (!g .test (Op .apply (sum , Dat [l ]))) {
176+ while (l < N ) {
177+ push (l );
178+ l = l << 1 ;
179+ if (g .test (Op .apply (sum , Dat [l ]))) {
180+ sum = Op .apply (sum , Dat [l ]);
181+ l ++;
182+ }
183+ }
184+ return l - N ;
185+ }
186+ sum = Op .apply (sum , Dat [l ]);
187+ l ++;
188+ } while ((l & -l ) != l );
189+ return MAX ;
190+ }
191+
192+ public int minLeft (int r , java .util .function .Predicate <S > g ) {
193+ inclusiveRangeCheck (r );
194+ if (!f .test (E )) {
195+ throw new IllegalArgumentException ("Identity element must satisfy the condition." );
196+ }
197+ if (r == 0 ) return 0 ;
198+ r += N ;
199+ pushTo (r - 1 );
200+ S sum = E ;
201+ do {
202+ r --;
203+ while (r > 1 && (r & 1 ) == 1 ) r >>= 1 ;
204+ if (!g .test (Op .apply (Dat [r ], sum ))) {
205+ while (r < N ) {
206+ push (r );
207+ r = r << 1 | 1 ;
208+ if (g .test (Op .apply (Dat [r ], sum ))) {
209+ sum = Op .apply (Dat [r ], sum );
210+ r --;
211+ }
212+ }
213+ return r + 1 - N ;
214+ }
215+ sum = Op .apply (Dat [r ], sum );
216+ } while ((r & -r ) != r );
217+ return 0 ;
218+ }
219+
220+ private void exclusiveRangeCheck (int p ) {
221+ if (p < 0 || p >= MAX ) {
222+ throw new IndexOutOfBoundsException (
223+ String .format ("Index %d is not in [%d, %d)." , p , 0 , MAX )
224+ );
225+ }
226+ }
227+
228+ private void inclusiveRangeCheck (int p ) {
229+ if (p < 0 || p > MAX ) {
230+ throw new IndexOutOfBoundsException (
231+ String .format ("Index %d is not in [%d, %d]." , p , 0 , MAX )
232+ );
233+ }
234+ }
235+ }
0 commit comments