1
+ /* *
2
+ * @file 6061.cpp
3
+ * @author Macesuted ([email protected] )
4
+ * @date 2022-06-04
5
+ *
6
+ * @copyright Copyright (c) 2022
7
+ *
8
+ */
9
+
10
+ #include < bits/stdc++.h>
11
+ using namespace std ;
12
+
13
+ #ifndef LOCAL
14
+ #define endl ' \n '
15
+ #endif
16
+
17
+ bool mem1;
18
+
19
+ #define maxn 100005
20
+ #define mod 1000000007
21
+
22
+ typedef tuple<int , int , int > tiii;
23
+
24
+ int id[maxn << 1 ];
25
+
26
+ class FhqTreap1 {
27
+ private:
28
+ struct Node {
29
+ Node *l, *r;
30
+ int siz, id, rnk;
31
+ bool ali, era;
32
+ Node (int id_) { l = r = nullptr , siz = 1 , ali = true , era = false , rnk = rand (), id = id_; }
33
+ };
34
+
35
+ Node* root;
36
+ int n, cnt;
37
+
38
+ int getSiz (Node* p) { return p ? p->siz : 0 ; }
39
+ void clear (Node* p) { return p && (p->era = true , p->ali = false , p->siz = 0 ), void (); }
40
+ void pushDown (Node* p) { return p->era && (clear (p->l ), clear (p->r ), p->era = false ), void (); }
41
+ void pushUp (Node* p) { return p->siz = p->ali + getSiz (p->l ) + getSiz (p->r ), void (); }
42
+ void split (Node* p, Node*& t1, Node*& t2, int siz) {
43
+ if (!p) return t1 = t2 = nullptr , void ();
44
+ pushDown (p);
45
+ if (p->ali + getSiz (p->l ) <= siz)
46
+ t1 = p, split (p->r , t1->r , t2, siz - p->ali - getSiz (p->l ));
47
+ else
48
+ t2 = p, split (p->l , t1, t2->l , siz);
49
+ return pushUp (p);
50
+ }
51
+ void merge (Node*& p, Node* t1, Node* t2) {
52
+ if (!t1) return p = t2, void ();
53
+ if (!t2) return p = t1, void ();
54
+ if (t1->rnk < t2->rnk )
55
+ pushDown (p = t1), merge (p->r , t1->r , t2);
56
+ else
57
+ pushDown (p = t2), merge (p->l , t1, t2->l );
58
+ return pushUp (p);
59
+ }
60
+ void getId (Node* p) {
61
+ if (!p) return ;
62
+ return getId (p->l ), id[p->id ] = ++cnt, getId (p->r ), delete p;
63
+ }
64
+
65
+ public:
66
+ FhqTreap1 (void ) { root = nullptr ; }
67
+ void build (int n_) {
68
+ n = n_;
69
+ for (int i = 1 ; i <= n; i++) merge (root, root, new Node (i));
70
+ return ;
71
+ }
72
+ void insert (int p) {
73
+ Node* tr = nullptr ;
74
+ return split (root, root, tr, p), merge (root, root, new Node (++n)), merge (root, root, tr);
75
+ }
76
+ void erase (int p) {
77
+ Node *tp = nullptr , *tr = nullptr ;
78
+ split (root, root, tp, p - 1 ), split (tp, tp, tr, 1 ), clear (tp);
79
+ return merge (root, root, tp), merge (root, root, tr);
80
+ }
81
+ void getId (void ) { return cnt = 0 , getId (root); }
82
+ };
83
+
84
+ class FhqTreap2 {
85
+ private:
86
+ struct Node {
87
+ Node *l, *r;
88
+ int siz, rnk, id;
89
+ Node (int id_) { l = r = nullptr , siz = 1 , rnk = rand (), id = id_; }
90
+ };
91
+
92
+ Node* root;
93
+
94
+ int getSiz (Node* p) { return p ? p->siz : 0 ; }
95
+ void pushUp (Node* p) { return p->siz = 1 + getSiz (p->l ) + getSiz (p->r ), void (); }
96
+ void split (Node* p, Node*& t1, Node*& t2, int siz) {
97
+ if (!p) return t1 = t2 = nullptr , void ();
98
+ if (1 + getSiz (p->l ) <= siz)
99
+ t1 = p, split (p->r , t1->r , t2, siz - 1 - getSiz (p->l ));
100
+ else
101
+ t2 = p, split (p->l , t1, t2->l , siz);
102
+ return pushUp (p);
103
+ }
104
+ void merge (Node*& p, Node* t1, Node* t2) {
105
+ if (!t1) return p = t2, void ();
106
+ if (!t2) return p = t1, void ();
107
+ if (t1->rnk < t2->rnk )
108
+ p = t1, merge (p->r , t1->r , t2);
109
+ else
110
+ p = t2, merge (p->l , t1, t2->l );
111
+ return pushUp (p);
112
+ }
113
+
114
+ public:
115
+ FhqTreap2 (void ) { root = nullptr ; }
116
+ void insert (int p, int v) {
117
+ Node* tr = nullptr ;
118
+ return split (root, root, tr, p), merge (root, root, new Node (v)), merge (root, root, tr);
119
+ }
120
+ void erase (int p) {
121
+ Node *tp = nullptr , *tr = nullptr ;
122
+ split (root, root, tp, p - 1 ), split (tp, tp, tr, 1 ), delete tp;
123
+ return merge (root, root, tr);
124
+ }
125
+ int getId (int p) {
126
+ Node *tp = nullptr , *tr = nullptr ;
127
+ split (root, root, tp, p - 1 ), split (tp, tp, tr, 1 );
128
+ int ret = tp->id ;
129
+ return merge (root, root, tp), merge (root, root, tr), ret;
130
+ }
131
+ };
132
+
133
+ class FenwickTree {
134
+ private:
135
+ struct Value {
136
+ int64_t v1, v2, v3;
137
+ int cnt;
138
+ Value (void ) { v1 = v2 = v3 = cnt = 0 ; }
139
+ Value (int v) { v1 = v, v2 = v3 = 0 , cnt = 1 ; }
140
+ Value (int64_t v1_, int64_t v2_, int64_t v3_, int cnt_) { v1 = v1_, v2 = v2_, v3 = v3_, cnt = cnt_; }
141
+ Value operator +(const Value& o) const {
142
+ return Value{(v1 + o.v1 ) % mod, (v2 + v1 * o.v1 + o.v2 ) % mod, (v3 + v2 * o.v1 + v1 * o.v2 + o.v3 ) % mod,
143
+ cnt + o.cnt };
144
+ }
145
+ };
146
+
147
+ class SegmentTree {
148
+ private:
149
+ struct Node {
150
+ Node *l, *r;
151
+ Value val;
152
+ Node (void ) { l = r = nullptr ; }
153
+ };
154
+
155
+ Node* root;
156
+ int n;
157
+
158
+ void pushUp (Node* p) { return p->val = (p->l ? p->l ->val : Value ()) + (p->r ? p->r ->val : Value ()), void (); }
159
+ void insert (Node*& p, int l, int r, int qp, int v) {
160
+ if (!p) p = new Node ();
161
+ if (l == r) return p->val = Value (v), void ();
162
+ int mid = (l + r) >> 1 ;
163
+ qp <= mid ? insert (p->l , l, mid, qp, v) : insert (p->r , mid + 1 , r, qp, v);
164
+ return pushUp (p);
165
+ }
166
+ void erase (Node*& p, int l, int r, int qp) {
167
+ if (l == r) return delete p, p = nullptr , void ();
168
+ int mid = (l + r) >> 1 ;
169
+ qp <= mid ? erase (p->l , l, mid, qp) : erase (p->r , mid + 1 , r, qp);
170
+ pushUp (p);
171
+ if (!p->val .cnt ) delete p, p = nullptr ;
172
+ return ;
173
+ }
174
+ Value query (Node* p, int l, int r, int ql, int qr) {
175
+ if (!p) return Value ();
176
+ if (ql <= l && r <= qr) return p->val ;
177
+ int mid = (l + r) >> 1 ;
178
+ if (qr <= mid) return query (p->l , l, mid, ql, qr);
179
+ if (ql > mid) return query (p->r , mid + 1 , r, ql, qr);
180
+ return query (p->l , l, mid, ql, qr) + query (p->r , mid + 1 , r, ql, qr);
181
+ }
182
+
183
+ public:
184
+ SegmentTree (void ) { root = nullptr ; }
185
+ void resize (int n_) { return n = n_, void (); }
186
+ void insert (int p, int v) { return insert (root, 1 , n, p, v); }
187
+ void erase (int p) { return erase (root, 1 , n, p); }
188
+ Value query (int l, int r) { return query (root, 1 , n, l, r); }
189
+ };
190
+
191
+ SegmentTree tree[maxn << 1 ];
192
+ int n;
193
+
194
+ Value query (int xl, int xr, int yr) {
195
+ Value ans;
196
+ for (int i = yr; i; i -= i & -i) ans = ans + tree[i].query (xl, xr);
197
+ return ans;
198
+ }
199
+
200
+ public:
201
+ void build (int n_) {
202
+ n = n_;
203
+ for (int i = 1 ; i <= n; i++) tree[i].resize (n);
204
+ return ;
205
+ }
206
+ void insert (int x, int y, int v) {
207
+ for (int i = y + 1 ; i <= n; i += i & -i) tree[i].insert (x, v);
208
+ return ;
209
+ }
210
+ void erase (int x, int y) {
211
+ for (int i = y + 1 ; i <= n; i += i & -i) tree[i].erase (x);
212
+ return ;
213
+ }
214
+ int64_t querySum (int xl, int xr, int yr) { return query (xl, xr, yr + 1 ).v3 ; }
215
+ int64_t queryCnt (int xl, int xr, int yr) { return query (xl, xr, yr + 1 ).cnt ; }
216
+ };
217
+
218
+ FhqTreap1 BT1;
219
+ FhqTreap2 BT2;
220
+ FenwickTree FT;
221
+ int a[maxn], v[maxn << 1 ];
222
+ tiii ques[maxn];
223
+ map<int , set<int >> pos;
224
+
225
+ int getLeft (int x) {
226
+ auto p = pos[v[x]].find (x);
227
+ return p == pos[v[x]].begin () ? 0 : *--p;
228
+ }
229
+ int getRight (int x) {
230
+ auto p = pos[v[x]].find (x);
231
+ return ++p == pos[v[x]].end () ? 0 : *p;
232
+ }
233
+ void insert (int x) {
234
+ pos[v[x]].insert (x);
235
+ int l = getLeft (x), r = getRight (x);
236
+ FT.insert (x, l, v[x]);
237
+ if (r) FT.erase (r, l), FT.insert (r, x, v[r]);
238
+ return ;
239
+ }
240
+ void erase (int x) {
241
+ int l = getLeft (x), r = getRight (x);
242
+ pos[v[x]].erase (x);
243
+ FT.erase (x, l);
244
+ if (r) FT.erase (r, x), FT.insert (r, l, v[r]);
245
+ return ;
246
+ }
247
+
248
+ void solve (void ) {
249
+ int n, q;
250
+ cin >> n >> q;
251
+ int tn = n;
252
+ for (int i = 1 ; i <= n; i++) cin >> a[i];
253
+ for (int i = 1 ; i <= q; i++) {
254
+ cin >> get<0 >(ques[i]) >> get<1 >(ques[i]);
255
+ if (get<0 >(ques[i]) != 3 ) cin >> get<2 >(ques[i]);
256
+ }
257
+ BT1.build (n);
258
+ for (int i = 1 ; i <= q; i++) {
259
+ if (get<0 >(ques[i]) == 3 ) BT1.erase (get<1 >(ques[i]));
260
+ if (get<0 >(ques[i]) == 4 ) BT1.insert (get<1 >(ques[i])), n++;
261
+ }
262
+ BT1.getId (), FT.build (n);
263
+ for (int i = 1 ; i <= tn; i++) v[id[i]] = a[i], insert (id[i]), BT2.insert (i - 1 , id[i]);
264
+ for (int i = 1 , t, x, y, c = tn; i <= q; i++) {
265
+ tie (t, x, y) = ques[i];
266
+ if (t == 1 ) x = BT2.getId (x), y = BT2.getId (y), cout << FT.querySum (x, y, x - 1 ) << endl;
267
+ if (t == 2 ) x = BT2.getId (x), erase (x), v[x] = y, insert (x);
268
+ if (t == 3 ) x = BT2.getId (x), erase (x), BT2.erase (get<1 >(ques[i]));
269
+ if (t == 4 ) v[x = id[++c]] = y, insert (x), BT2.insert (get<1 >(ques[i]), x);
270
+ if (t == 5 ) x = BT2.getId (x), y = BT2.getId (y), cout << FT.queryCnt (x, y, x - 1 ) << endl;
271
+ }
272
+ return ;
273
+ }
274
+
275
+ bool mem2;
276
+
277
+ int main () {
278
+ ios::sync_with_stdio (false ), cin.tie (nullptr );
279
+ #ifdef LOCAL
280
+ cerr << " Memory Cost: " << abs (&mem1 - &mem2) / 1024 . / 1024 . << " MB" << endl;
281
+ #endif
282
+
283
+ int _ = 1 ;
284
+ while (_--) solve ();
285
+
286
+ #ifdef LOCAL
287
+ cerr << " Time Cost: " << clock () * 1000 . / CLOCKS_PER_SEC << " MS" << endl;
288
+ #endif
289
+ return 0 ;
290
+ }
0 commit comments