1+ // mp-oi-library extension note: start. Do not modify this part.
2+ // mp-oi-library extension header: library version: @MrPython-0.2.6
3+ // mp-oi-library extension note: file bits.hpp
4+ #ifndef MP_LIBRARY_BITS
5+ #define MP_LIBRARY_BITS
6+ #include < limits>
7+ namespace mrpython {
8+ unsigned countl_zero (unsigned x) { return __builtin_clz (x); }
9+ unsigned countl_zero (unsigned long x) { return __builtin_clzl (x); }
10+ unsigned countl_zero (unsigned long long x) { return __builtin_clzll (x); }
11+ unsigned countr_zero (unsigned x) { return __builtin_ctz (x); }
12+ unsigned countr_zero (unsigned long x) { return __builtin_ctzl (x); }
13+ unsigned countr_zero (unsigned long long x) { return __builtin_ctzll (x); }
14+ unsigned int_log2 (unsigned n) {
15+ return std::numeric_limits<unsigned >::digits - 1 - countl_zero (n);
16+ }
17+ unsigned long int_log2 (unsigned long n) {
18+ return std::numeric_limits<unsigned long >::digits - 1 - countl_zero (n);
19+ }
20+ unsigned long long int_log2 (unsigned long long n) {
21+ return std::numeric_limits<unsigned long long >::digits - 1 - countl_zero (n);
22+ }
23+ unsigned lowbit (unsigned x) { return x & -x; }
24+ unsigned long lowbit (unsigned long x) { return x & -x; }
25+ unsigned long long lowbit (unsigned long long x) { return x & -x; }
26+ unsigned highbit (unsigned x) { return (unsigned )1 << int_log2 (x); }
27+ unsigned long highbit (unsigned long x) {
28+ return (unsigned long )1 << int_log2 (x);
29+ }
30+ unsigned long long highbit (unsigned long long x) {
31+ return (unsigned long long )1 << int_log2 (x);
32+ }
33+ } // namespace mrpython
34+ #endif
35+ // mp-oi-library extension note: file lazy_segment_tree.hpp
36+
37+ #ifndef MP_LIBRARY_LAZY_SEGMENT_TREE_HPP
38+ #define MP_LIBRARY_LAZY_SEGMENT_TREE_HPP
39+ #include < algorithm>
40+ #include < functional>
41+ #include < vector>
42+
43+ namespace mrpython {
44+ using std::size_t ;
45+ template <typename T, typename MergeFunction, typename Lazy,
46+ typename OperateFunction, typename MergeLazyFunction>
47+ class lazy_segment_tree {
48+ std::vector<T> data;
49+ std::vector<Lazy> lazy;
50+ std::vector<size_t > size;
51+ size_t n;
52+ Lazy lazyInit;
53+ MergeFunction mergeData;
54+ OperateFunction operate;
55+ MergeLazyFunction mergeLazy;
56+ void build (void ) {
57+ data.reserve (2 * n - 1 ), size.reserve (2 * n - 1 );
58+ for (size_t i = n; i < 2 * n - 1 ; ++i) {
59+ size_t d = 2 * n - 1 - i;
60+ size_t l = d * 2 , r = d * 2 + 1 ;
61+ data.emplace_back (mergeData (data[2 * n - 1 - l], data[2 * n - 1 - r]));
62+ size.emplace_back (size[2 * n - 1 - l] + size[2 * n - 1 - r]);
63+ }
64+ std::reverse (data.begin (), data.end ());
65+ std::reverse (size.begin (), size.end ());
66+ }
67+ void pushdown (size_t pos) {
68+ if (size[pos] == 1 ) {
69+ lazy[pos] = lazyInit;
70+ return ;
71+ }
72+ add_tag_for_node (2 * pos + 1 , lazy[pos]);
73+ add_tag_for_node (2 * pos + 2 , lazy[pos]);
74+ lazy[pos] = lazyInit;
75+ }
76+ void add_tag_for_node (size_t pos, Lazy const & lazyVal) {
77+ data[pos] = operate (lazyVal, data[pos], size[pos]);
78+ lazy[pos] = mergeLazy (lazy[pos], lazyVal);
79+ }
80+ T get_impl (size_t l, size_t r, size_t pos) {
81+ if (l == 0 && r == size[pos]) return data[pos];
82+ pushdown (pos);
83+ size_t m = size[pos * 2 + 1 ];
84+ if (l < m && r > m)
85+ return mergeData (get_impl (l, m, pos * 2 + 1 ),
86+ get_impl (0 , r - m, pos * 2 + 2 ));
87+ else if (l < m)
88+ return get_impl (l, r, pos * 2 + 1 );
89+ else if (r > m)
90+ return get_impl (l - m, r - m, pos * 2 + 2 );
91+ else
92+ __builtin_unreachable ();
93+ }
94+ void set_impl (size_t l, size_t r, Lazy const & operateVal, size_t pos) {
95+ if (l == 0 && r == size[pos]) return add_tag_for_node (pos, operateVal);
96+ pushdown (pos);
97+ size_t m = size[pos * 2 + 1 ];
98+ if (l < m && r > m)
99+ set_impl (l, m, operateVal, pos * 2 + 1 ),
100+ set_impl (0 , r - m, operateVal, pos * 2 + 2 );
101+ else if (l < m)
102+ set_impl (l, r, operateVal, pos * 2 + 1 );
103+ else if (r > m)
104+ set_impl (l - m, r - m, operateVal, pos * 2 + 2 );
105+ else
106+ __builtin_unreachable ();
107+ data[pos] = mergeData (data[pos * 2 + 1 ], data[pos * 2 + 2 ]);
108+ }
109+
110+ public:
111+ template <typename InputIterator>
112+ lazy_segment_tree (InputIterator first, InputIterator last,
113+ Lazy const & lazyInitVal,
114+ MergeFunction const & mergeDataFun = MergeFunction(),
115+ OperateFunction const & OperateFun = OperateFunction(),
116+ MergeLazyFunction const & mergeTagFun = MergeLazyFunction())
117+ : data(first, last),
118+ lazy (2 * data.size() - 1, lazyInitVal),
119+ size(data.size(), 1),
120+ n(data.size()),
121+ lazyInit(lazyInitVal),
122+ mergeData(mergeDataFun),
123+ operate(OperateFun),
124+ mergeLazy(mergeTagFun) {
125+ rotate (data.begin (), data.begin () + (2 * n - 1 ) - (highbit (2 * n - 1 ) - 1 ),
126+ data.end ());
127+ reverse (data.begin (), data.end ());
128+ build ();
129+ }
130+ lazy_segment_tree (size_t len, T const & init, Lazy const & lazyInitVal,
131+ MergeFunction const & mergeDataFun = MergeFunction(),
132+ OperateFunction const & OperateFun = OperateFunction(),
133+ MergeLazyFunction const & mergeTagFun = MergeLazyFunction())
134+ : data(len, init),
135+ lazy(2 * len - 1 , lazyInitVal),
136+ size(len, 1 ),
137+ n(len),
138+ lazyInit(lazyInitVal),
139+ mergeData(mergeDataFun),
140+ operate(OperateFun),
141+ mergeLazy(mergeTagFun) {
142+ build ();
143+ }
144+ T get (size_t l, size_t r) { return get_impl (l, r, 0 ); }
145+ void set (size_t l, size_t r, Lazy const & operateVal) {
146+ set_impl (l, r, operateVal, 0 );
147+ }
148+ };
149+ template <typename T> struct lazy_segment_tree_add_add_operate_function {
150+ T operator ()(T const & lazy, T const & data, size_t size) const {
151+ return data + lazy * size;
152+ }
153+ };
154+ template <typename T>
155+ using lazy_segment_tree_add_add =
156+ lazy_segment_tree<T, std::plus<T>, T,
157+ lazy_segment_tree_add_add_operate_function<T>,
158+ std::plus<T>>;
159+
160+ template <typename NodeStruct> class lazy_segment_tree_from_node {
161+ using T = typename NodeStruct::T;
162+ using Lazy = typename NodeStruct::Lazy;
163+ struct MergeFunction {
164+ T operator ()(T const & a, T const & b) const {
165+ return NodeStruct::merge_data (a, b);
166+ }
167+ };
168+ struct OperateFunction {
169+ T operator ()(Lazy const & lazy, T const & data, size_t size) const {
170+ return NodeStruct::operate (lazy, data, size);
171+ }
172+ };
173+ struct MergeLazyFunction {
174+ Lazy operator ()(Lazy const & a, Lazy const & b) const {
175+ return NodeStruct::merge_lazy (a, b);
176+ }
177+ };
178+ lazy_segment_tree_from_node () = delete ;
179+
180+ public:
181+ using type = lazy_segment_tree<T, MergeFunction, Lazy, OperateFunction,
182+ MergeLazyFunction>;
183+ };
184+ } // namespace mrpython
185+ #endif
186+
187+ // mp-oi-library extension note: end
188+ #include < bits/stdc++.h>
189+ using namespace std ;
190+ istream& fin = cin;
191+ ostream& fout = cout;
192+ using ui = unsigned int ;
193+ using uli = unsigned long long int ;
194+ using li = long long int ;
195+ int main (void ) {
196+ ios::sync_with_stdio (false ), cin.tie (nullptr ), cout.tie (nullptr );
197+ size_t n, m;
198+ fin >> n >> m;
199+ vector<li> a (n);
200+ for (li& i : a) fin >> i;
201+ mrpython::lazy_segment_tree_add_add<li> tree (a.begin (), a.end (), 0 );
202+ while (m--) {
203+ char op;
204+ size_t x, y;
205+ fin >> op >> x >> y;
206+ --x;
207+ if (op == ' 1' ) {
208+ size_t k;
209+ fin >> k;
210+ tree.set (x, y, k);
211+ }
212+ if (op == ' 2' ) { fout << tree.get (x, y) << ' \n ' ; }
213+ }
214+ return 0 ;
215+ }
0 commit comments