1
+ #include < bits/stdc++.h>
2
+ using namespace std ;
3
+
4
+ #define ls (x ) ((x) << 1 )
5
+ #define rs (x ) (((x) << 1 ) | 1 )
6
+ #define mid (l, r ) (((l) + (r)) >> 1 )
7
+
8
+ typedef pair<size_t , size_t > Interval;
9
+
10
+ bool isInterSect (Interval r1, Interval r2) {
11
+ if (r1.first > r2.first ) swap (r1, r2);
12
+ /* r1.first <= r2.first */
13
+ if (r1.second >= r2.first ) return true ;
14
+ return false ;
15
+ }
16
+
17
+ template <typename T>
18
+ class SegTree {
19
+ private:
20
+ vector<T> tree, tag;
21
+ // int n, n4;
22
+
23
+ const vector<T>& arrRef;
24
+ const size_t mRoot = 1 , mRootStart = 1 , mRootEnd ;
25
+
26
+ void build (const size_t root, const size_t start, const size_t end);
27
+ void pushup (const size_t root);
28
+ void pushdown (const size_t root, const size_t curStart,
29
+ const size_t curEnd);
30
+ void addtag (const size_t root, const size_t curStart, const size_t curEnd,
31
+ const T val);
32
+ void intervalUpdateImpl (const size_t start, const size_t end, const T val,
33
+ const size_t root, const size_t curStart,
34
+ const size_t curEnd);
35
+ T getIntervalSumImpl (const size_t start, const size_t end,
36
+ const size_t root, const size_t curStart,
37
+ const size_t curEnd);
38
+
39
+ public:
40
+ SegTree (const vector<T>& arr)
41
+ : mRootEnd (arr.size()), arrRef(arr), tree(arr.size() << 2 , 0 ),
42
+ tag (arr.size() << 2, 0) {
43
+ /* idx start from 1*/
44
+ assert (arr.size () >= 1 and arr.at (0 ) == 0 );
45
+ build (mRoot , mRootStart , mRootEnd );
46
+ }
47
+
48
+ void intervalUpdate (const size_t start, const size_t end, const T val);
49
+
50
+ T getIntervalSum (const size_t start, const size_t end);
51
+ };
52
+ template <typename T>
53
+ void SegTree<T>::build(const size_t root, const size_t start,
54
+ const size_t end) {
55
+ /* leaf node */
56
+ if (start == end) {
57
+ tree[root] = arrRef[start];
58
+ return ;
59
+ }
60
+ /* divide */
61
+ const size_t Mid = mid (start, end);
62
+
63
+ build (ls (root), start, Mid);
64
+ build (rs (root), Mid + 1 , end);
65
+ /* calc root */
66
+ pushup (root);
67
+ }
68
+ template <typename T>
69
+ void SegTree<T>::pushup(const size_t root) {
70
+ /* gather children value, push up to root */
71
+ /* interval sum */
72
+ tree[root] = tree[ls (root)] + tree[rs (root)];
73
+ /* max/min */
74
+ // tree[root] = min(tree[ls(root)], tree[rs(root)]);
75
+ }
76
+ template <typename T>
77
+ void SegTree<T>::pushdown(const size_t root, const size_t curStart,
78
+ const size_t curEnd) {
79
+ /* push root tag to children,
80
+ because we need to update child interval of root,
81
+ so the tag of root will be invalid,
82
+ but its children must record root's tag */
83
+ if (tag[root]) {
84
+ const size_t curMid = mid (curStart, curEnd);
85
+ addtag (ls (root), curStart, curMid, tag[root]);
86
+ addtag (rs (root), curMid + 1 , curEnd, tag[root]);
87
+ tag[root] = 0 ;
88
+ }
89
+ }
90
+
91
+ template <typename T>
92
+ void SegTree<T>::addtag(const size_t root, const size_t curStart,
93
+ const size_t curEnd, const T val) {
94
+ assert (curStart <= curEnd);
95
+ tag[root] += val;
96
+ tree[root] += val * (curEnd - curStart + 1 );
97
+ }
98
+ template <typename T>
99
+ void SegTree<T>::intervalUpdate(const size_t start, const size_t end,
100
+ const T val) {
101
+ intervalUpdateImpl (start, end, val, mRoot , mRootStart , mRootEnd );
102
+ }
103
+ template <typename T>
104
+ void SegTree<T>::intervalUpdateImpl(const size_t start, const size_t end,
105
+ const T val, const size_t root,
106
+ const size_t curStart,
107
+ const size_t curEnd) {
108
+ assert (curStart <= curEnd);
109
+ /* assert Intersect */
110
+ assert (isInterSect ({ start, end }, { curStart, curEnd }));
111
+ /* query interval complete cover cur node interval
112
+ ** start <= curStart ~ curEnd <= end */
113
+ if (start <= curStart and curEnd <= end) {
114
+ addtag (root, curStart, curEnd, val);
115
+ return ;
116
+ }
117
+ /* else: cur Interval of root is not in [start, end],
118
+ ** need divide and conquer */
119
+ /* firstly, pushdown root tag to children */
120
+ pushdown (root, curStart, curEnd);
121
+ /* then recursively divide and conquer */
122
+ const size_t curMid = mid (curStart, curEnd);
123
+ /* left child tree */
124
+ if (curMid >= start)
125
+ intervalUpdateImpl (start, end, val, ls (root), curStart, curMid);
126
+ /* right child tree */
127
+ if (curMid + 1 <= end)
128
+ intervalUpdateImpl (start, end, val, rs (root), curMid + 1 , curEnd);
129
+ /* update root */
130
+ pushup (root);
131
+ }
132
+ template <typename T>
133
+ T SegTree<T>::getIntervalSumImpl(const size_t start, const size_t end,
134
+ const size_t root, const size_t curStart,
135
+ const size_t curEnd) {
136
+ assert (curStart <= curEnd);
137
+
138
+ /* query interval complete cover cur node interval, return tree[root]
139
+ start <= curStart and curEnd <= end */
140
+ if (start <= curStart and curEnd <= end) { return tree[root]; }
141
+ /* not complete cover */
142
+ pushdown (root, curStart, curEnd);
143
+ T res = 0 ;
144
+ const size_t curMid = mid (curStart, curEnd);
145
+ if (curMid >= start)
146
+ res += getIntervalSumImpl (start, end, ls (root), curStart, curMid);
147
+ if (curMid + 1 <= end)
148
+ res += getIntervalSumImpl (start, end, rs (root), curMid + 1 , curEnd);
149
+ return res;
150
+ }
151
+ template <typename T>
152
+ T SegTree<T>::getIntervalSum(const size_t start, const size_t end) {
153
+ return getIntervalSumImpl (start, end, mRoot , mRootStart , mRootEnd );
154
+ }
155
+ bool debug = true ;
156
+
157
+ void testSegTree () {
158
+ vector<int > arr = { 0 , 1 , 2 , 3 , 4 , 5 , 6 };
159
+ SegTree<int > segtree (arr);
160
+ function<void (const size_t start, const size_t end, bool debug)>
161
+ testIntervalSum;
162
+ function<void (const size_t start, const size_t end, const int val)>
163
+ testIntervalUpdate;
164
+
165
+ testIntervalSum = [&arr, &segtree](const size_t start, const size_t end,
166
+ bool debug) {
167
+ auto stdAns = accumulate (arr.begin () + start, arr.begin () + end + 1 , 0 );
168
+ auto stAns = segtree.getIntervalSum (start, end);
169
+ if (stdAns != stAns) { cout << " wrong ans!" << endl; }
170
+ if (debug) {
171
+ cout << " test Interval Sum: [" << start << " , " << end << " ]"
172
+ << endl;
173
+ cout << " Standerd Ans: " << stdAns << endl;
174
+ cout << " SegTree Ans " << stdAns << endl;
175
+ }
176
+ };
177
+ for (int s = 1 ; s <= arr.size (); s++) {
178
+ for (int e = s; e <= arr.size (); e++) { testIntervalSum (s, e, false ); }
179
+ }
180
+
181
+ testIntervalUpdate = [&arr, &segtree, testIntervalSum](const size_t start,
182
+ const size_t end,
183
+ const int val) {
184
+ //
185
+ for (int i = start; i <= end; i++) { arr[i] += val; }
186
+ cout << " arr: " << endl;
187
+ for (int i = 0 ; i < arr.size (); i++) { cout << arr[i] << " " ; }
188
+ cout << endl;
189
+ segtree.intervalUpdate (start, end, val);
190
+ testIntervalSum (start, end, true );
191
+ };
192
+ testIntervalUpdate (1 , 2 , 5 );
193
+ testIntervalUpdate (1 , 3 , -2 );
194
+ testIntervalUpdate (2 , 2 , 1 );
195
+ testIntervalUpdate (5 , 5 , -3 );
196
+ }
197
+
198
+ typedef uint64_t ull;
199
+ typedef int64_t ll;
200
+
201
+ const int N = 1e5 + 10 ;
202
+ size_t n, m;
203
+ vector<ll> arr (N);
204
+
205
+ int main () {
206
+ cin >> n >> m;
207
+ for (int i = 1 ; i <= n; i++) { cin >> arr[i]; }
208
+ arr.resize (n + 1 );
209
+ SegTree<ll> segtree (arr);
210
+ while (m--) {
211
+ int q, x, y;
212
+ cin >> q;
213
+ if (q == 1 ) {
214
+ /* 1 x y k */
215
+ ll k;
216
+ cin >> x >> y >> k;
217
+ segtree.intervalUpdate (x, y, k);
218
+ } else if (q == 2 ) {
219
+ cin >> x >> y;
220
+ cout << segtree.getIntervalSum (x, y) << endl;
221
+ } else {
222
+ assert (false );
223
+ }
224
+ }
225
+
226
+ return 0 ;
227
+ }
0 commit comments