11// mp-oi-library extension note: start. Do not modify this part.
2- // mp-oi-library extension header: library version: @MrPython-0.2.6
2+ // mp-oi-library extension header: library version: @MrPython-0.4.2
33// mp-oi-library extension note: file bits.hpp
44#ifndef MP_LIBRARY_BITS
55#define MP_LIBRARY_BITS
@@ -32,6 +32,30 @@ unsigned long long highbit(unsigned long long x) {
3232}
3333} // namespace mrpython
3434#endif
35+ // mp-oi-library extension note: file segment_tree_utility.hpp
36+ #ifndef MP_LIBRARY_SEGMENT_TREE_UTILITY_HPP
37+ #define MP_LIBRARY_SEGMENT_TREE_UTILITY_HPP
38+ #include < cstddef>
39+ #include < utility>
40+ namespace mrpython {
41+ template <typename F, typename T>
42+ auto call_merge_impl (F const & f, T const & lv, std::size_t ls, T const & rv,
43+ std::size_t rs, int ) -> decltype(f(lv, ls, rv, rs)) {
44+ return f (lv, ls, rv, rs);
45+ }
46+ template <typename F, typename T>
47+ auto call_merge_impl (F const & f, T const & lv, std::size_t , T const & rv,
48+ std::size_t , long ) -> decltype(f(lv, rv)) {
49+ return f (lv, rv);
50+ }
51+ template <typename F, typename T>
52+ decltype (auto ) call_merge(F const & f, T const & lv, std::size_t ls, T const & rv,
53+ std::size_t rs) {
54+ return call_merge_impl (f, lv, ls, rv, rs, 0 );
55+ }
56+ } // namespace mrpython
57+ #endif // MP_LIBRARY_SEGMENT_TREE_UTILITY_HPP
58+
3559// mp-oi-library extension note: file lazy_segment_tree.hpp
3660
3761#ifndef MP_LIBRARY_LAZY_SEGMENT_TREE_HPP
@@ -53,12 +77,22 @@ class lazy_segment_tree {
5377 MergeFunction mergeData;
5478 OperateFunction operate;
5579 MergeLazyFunction mergeLazy;
80+ auto doMergeData (std::pair<T const &, size_t > l,
81+ std::pair<T const &, size_t > r) {
82+ return std::make_pair (
83+ call_merge (mergeData, l.first , l.second , r.first , r.second ),
84+ l.second + r.second );
85+ }
86+ decltype (auto ) doMergeData(T const & lv, size_t ls, T const & rv, size_t rs) {
87+ return call_merge (mergeData, lv, ls, rv, rs);
88+ }
5689 void build (void ) {
5790 data.reserve (2 * n - 1 ), size.reserve (2 * n - 1 );
5891 for (size_t i = n; i < 2 * n - 1 ; ++i) {
5992 size_t d = 2 * n - 1 - i;
6093 size_t l = d * 2 , r = d * 2 + 1 ;
61- data.emplace_back (mergeData (data[2 * n - 1 - l], data[2 * n - 1 - r]));
94+ data.emplace_back (doMergeData (data[2 * n - 1 - l], size[2 * n - 1 - l],
95+ data[2 * n - 1 - r], size[2 * n - 1 - r]));
6296 size.emplace_back (size[2 * n - 1 - l] + size[2 * n - 1 - r]);
6397 }
6498 std::reverse (data.begin (), data.end ());
@@ -77,13 +111,13 @@ class lazy_segment_tree {
77111 data[pos] = operate (lazyVal, data[pos], size[pos]);
78112 lazy[pos] = mergeLazy (lazy[pos], lazyVal);
79113 }
80- T get_impl (size_t l, size_t r, size_t pos) {
81- if (l == 0 && r == size[pos]) return data[pos];
114+ std::pair<T, size_t > get_impl (size_t l, size_t r, size_t pos) {
115+ if (l == 0 && r == size[pos]) return { data[pos], size[pos]} ;
82116 pushdown (pos);
83117 size_t m = size[pos * 2 + 1 ];
84118 if (l < m && r > m)
85- return mergeData (get_impl (l, m, pos * 2 + 1 ),
86- get_impl (0 , r - m, pos * 2 + 2 ));
119+ return doMergeData (get_impl (l, m, pos * 2 + 1 ),
120+ get_impl (0 , r - m, pos * 2 + 2 ));
87121 else if (l < m)
88122 return get_impl (l, r, pos * 2 + 1 );
89123 else if (r > m)
@@ -104,7 +138,35 @@ class lazy_segment_tree {
104138 set_impl (l - m, r - m, operateVal, pos * 2 + 2 );
105139 else
106140 __builtin_unreachable ();
107- data[pos] = mergeData (data[pos * 2 + 1 ], data[pos * 2 + 2 ]);
141+ data[pos] = doMergeData (data[pos * 2 + 1 ], size[pos * 2 + 1 ],
142+ data[pos * 2 + 2 ], size[pos * 2 + 2 ]);
143+ }
144+ template <typename Operate>
145+ void set_impl (size_t c, Operate const & opv, size_t pos) {
146+ if (size[pos] == 1 ) {
147+ data[pos] = opv ((T const &)data[pos]);
148+ return ;
149+ }
150+ pushdown (pos);
151+ size_t m = size[pos * 2 + 1 ];
152+ if (c < m)
153+ set_impl (c, opv, pos * 2 + 1 );
154+ else
155+ set_impl (c - m, opv, pos * 2 + 2 );
156+ data[pos] = doMergeData (data[pos * 2 + 1 ], size[pos * 2 + 1 ],
157+ data[pos * 2 + 2 ], size[pos * 2 + 2 ]);
158+ }
159+ size_t data_id_to_node_id (size_t x) {
160+ x += n - ((2 * n - 1 ) - (highbit (2 * n - 1 ) - 1 ));
161+ if (x >= n) x -= n;
162+ x += n - 1 ;
163+ return x;
164+ }
165+ size_t node_id_to_data_id (size_t x) {
166+ x -= n - 1 ;
167+ x += ((2 * n - 1 ) - (highbit (2 * n - 1 ) - 1 ));
168+ if (x >= n) x -= n;
169+ return x;
108170 }
109171
110172 public:
@@ -122,8 +184,8 @@ class lazy_segment_tree {
122184 mergeData(mergeDataFun),
123185 operate(OperateFun),
124186 mergeLazy(mergeTagFun) {
125- rotate (data.begin (), data. begin () + ( 2 * n - 1 ) - ( highbit ( 2 * n - 1 ) - 1 ),
126- data.end ());
187+ rotate (data.begin (),
188+ data.begin () + (( 2 * n - 1 ) - ( highbit ( 2 * n - 1 ) - 1 )), data. end ());
127189 reverse (data.begin (), data.end ());
128190 build ();
129191 }
@@ -141,10 +203,71 @@ class lazy_segment_tree {
141203 mergeLazy(mergeTagFun) {
142204 build ();
143205 }
144- T get (size_t l, size_t r) { return get_impl (l, r, 0 ); }
206+ T get (size_t l, size_t r) { return get_impl (l, r, 0 ).first ; }
207+ T getd (size_t l, size_t r, T const & e = {}) { return l == r ? e : get (l, r); }
145208 void set (size_t l, size_t r, Lazy const & operateVal) {
209+ if (l == r) return ;
146210 set_impl (l, r, operateVal, 0 );
147211 }
212+ template <typename Operate> void set (size_t p, Operate const & opv) {
213+ set_impl (p, opv, 0 );
214+ }
215+ template <typename Check>
216+ size_t find_first_right (size_t l, Check const & check) {
217+ if (l >= n) return l;
218+ set (l, [](T const & _) { return _; }); // 将一路上的节点都 pushdown 下去
219+ l = data_id_to_node_id (l);
220+ while (l % 2 == 1 ) l /= 2 ;
221+ while (l < 2 * n - 1 && check (data[l])) l = l * 2 + 1 ;
222+ if (l >= 2 * n - 1 ) return node_id_to_data_id (l / 2 );
223+ std::pair<T, size_t > v = {data[l], size[l]};
224+ while (true ) {
225+ ++l;
226+ if (!(l & (l + 1 ))) return n;
227+ while (l % 2 == 1 ) l /= 2 ;
228+ std::pair<T, size_t > vl = doMergeData (v, {data[l], size[l]});
229+ if (check (vl.first )) break ;
230+ v = std::move (vl);
231+ }
232+ while (l < n - 1 ) {
233+ pushdown (l);
234+ std::pair<T, size_t > vl =
235+ doMergeData (v, {data[l * 2 + 1 ], size[l * 2 + 1 ]});
236+ if (!check (vl.first ))
237+ l = l * 2 + 2 , v = std::move (vl);
238+ else
239+ l = l * 2 + 1 ;
240+ }
241+ return node_id_to_data_id (l);
242+ }
243+ template <typename Check>
244+ size_t find_last_left (size_t r, Check const & check) {
245+ if (r >= n) return r;
246+ set (r, [](T const & _) { return _; }); // 将一路上的节点都 pushdown 下去
247+ r = data_id_to_node_id (r);
248+ while (r && r % 2 == 0 ) r = (r - 1 ) / 2 ;
249+ while (r < 2 * n - 1 && check (data[r])) r = r * 2 + 2 ;
250+ if (r >= 2 * n - 1 ) return node_id_to_data_id ((r - 1 ) / 2 );
251+ std::pair<T, size_t > v = {data[r], size[r]};
252+ while (true ) {
253+ if (!(r & (r + 1 ))) return -1 ;
254+ --r;
255+ while (r % 2 == 0 ) r = (r - 1 ) / 2 ;
256+ std::pair<T, size_t > vl = doMergeData (v, {data[r], size[r]});
257+ if (check (vl.first )) break ;
258+ v = std::move (vl);
259+ }
260+ while (r < n - 1 ) {
261+ pushdown (r);
262+ std::pair<T, size_t > vr =
263+ doMergeData (v, {data[r * 2 + 2 ], size[r * 2 + 2 ]});
264+ if (!check (vr.first ))
265+ r = r * 2 + 1 , v = std::move (vr);
266+ else
267+ r = r * 2 + 2 ;
268+ }
269+ return node_id_to_data_id (r);
270+ }
148271};
149272template <typename T> struct lazy_segment_tree_add_add_operate_function {
150273 T operator ()(T const & lazy, T const & data, size_t size) const {
0 commit comments