-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathDecart tree with data reference.cpp
270 lines (255 loc) · 6.59 KB
/
Decart tree with data reference.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
//
// main.cpp
// practice
//
// Created by Mahmud on 12/10/17.
// Copyright © 2017 Mahmud. All rights reserved.
//
/*
Reference problem:
https://www.spoj.com/problems/CARDFLIP/
Except some solution based on sqrt decomposition, it seems the problem has only
the following solution which is based on decart trees.
Please, carefully read what kind of operations is requested in the statement.
*/
/*
O((N + Q) * log(N)) solution using Decart trees
The queries of type 1 and 2 are be handled in standard Decart tree implementations.
And in order to work with queries of type 3,
we can use the following approach:
--> Keep a parent link from each tree node.
--> Since we use pointers for each nodes, we can track any element using its pointer node... (<3)
--> If we are required to reverse any range, parent links will not be affected.
--> Update links when you do Merge/Split operations.
--> When type-3 query come, first do update update operations until you reach root node.
--> Finally, traverse the path to root and count sizes of skipped left subtrees till the root node.
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <functional>
#include <ctime>
#include <cassert>
using namespace std;
const int MAX = 100005;
const int _INFINITY = 1 << 30;
struct node{
int value;
int priority;
int subtree_value;
int subtreeSize;
bool reversed;
node* leftChild;
node* rightChild;
node* parent;
int state; // 0 --> left child, 1 --> right child
};
typedef node* tree;
int getValue(tree t){
return t? t->subtree_value : _INFINITY;
}
int getSize(tree t){
return t? t->subtreeSize : 0;
}
void update(tree t){
if(t) {
t->subtree_value = min(getValue(t->leftChild),
min(t->value, getValue(t->rightChild)));
t->subtreeSize = getSize(t->leftChild) + 1 + getSize(t->rightChild);
if (t->leftChild) {
t->leftChild->parent = t;
t->leftChild->state = 0;
}
if (t->rightChild) {
t->rightChild->parent = t;
t->rightChild->state = 1;
}
}
}
void push(tree t){
if(t && t->reversed){
update(t);
t->reversed = 0;
swap(t->leftChild, t->rightChild);
if(t->leftChild) {
t->leftChild->reversed ^= 1;
t->leftChild->state ^= 1;
}
if(t->rightChild) {
t->rightChild->reversed ^= 1;
t->rightChild->state ^= 1;
}
}
}
void Split(tree t, tree &l, tree &r, int pos, int add = 0){
if(!t)
return void(l = r = NULL);
push(t);
int cur_pos = getSize(t->leftChild) + add;
if(cur_pos + 1 <= pos) {
Split(t->rightChild, t->rightChild, r, pos, cur_pos + 1);
l = t;
}
else {
Split(t->leftChild, l, t->leftChild, pos, add);
r = t;
}
update(t);
}
void Merge(tree &t, tree l, tree r){
push(l);
push(r);
if(!l || !r)
t = l? l : r;
else if(l->priority > r->priority) {
Merge(l->rightChild, l->rightChild, r);
t = l;
}
else {
Merge(r->leftChild, l, r->leftChild);
t = r;
}
update(t);
}
tree Initialize(int key){
tree p = (tree)malloc(sizeof(node));
p->value = key;
p->priority = rand();
p->subtree_value = key;
p->subtreeSize = 1;
p->reversed = 0;
p->leftChild = NULL;
p->rightChild = NULL;
p->parent = NULL;
p->state = 0;
return p;
}
void Insert(tree &t, tree item, int position){
tree l1, r1;
Split(t, l1, r1, position - 1);
Merge(l1, l1, item);
Merge(t, l1, r1);
}
void Insert(tree &t, int position, int key){
tree p = Initialize(key);
Insert(t, p, position);
}
void Erase(tree &t, int position){
tree l1, r1;
Split(t, l1, r1, position - 1);
tree l2, r2;
Split(r1, l2, r2, 1);
Merge(t, l1, r2);
}
void Reverse(tree &t, int l, int r){
tree l1, r1;
Split(t, l1, r1, l - 1);
tree l2, r2;
Split(r1, l2, r2, r - l + 1);
l2->reversed ^= 1;
Merge(r1, l2, r2);
Merge(t, l1, r1);
}
int Query(tree &t, int l, int r){
tree l1, r1;
Split(t, l1, r1, l - 1);
tree l2, r2;
Split(r1, l2, r2, r - l + 1);
int ans = getValue(l2);
Merge(r1, l2, r2);
Merge(t, l1, r1);
return ans;
}
bool Find(tree t, int key){
push(t);
if(!t)
return false;
if(t->value == key)
return true;
if(t->value > key)
return Find(t->leftChild, key);
return Find(t->rightChild, key);
}
int Get_index(tree &t, int key, int add = 0){
push(t);
if(t->value == key && getValue(t->leftChild) > key)
return getSize(t->leftChild) + add + 1;
else if(getValue(t->leftChild) <= key)
return Get_index(t->leftChild, key, add);
return Get_index(t->rightChild, key, add + getSize(t->leftChild) + 1);
}
int Kth_element(tree t, int k){
push(t);
if(getSize(t->leftChild) + 1 == k)
return t->value;
if(getSize(t->leftChild) + 1 > k)
return Kth_element(t->leftChild, k);
return Kth_element(t->rightChild, k - getSize(t->leftChild) - 1);
}
void fixPath(tree &t) {
if (!t) return;
fixPath(t->parent);
push(t);
}
int calculatePosition(tree &t, int lastState) {
int skipped = 0;
if (lastState == 1) skipped = 1 + getSize(t->leftChild);
if (t->parent == NULL) return skipped;
else return skipped + calculatePosition(t->parent, t->state);
}
int positionOfElement(tree &t) {
fixPath(t);
return calculatePosition(t, +1);
}
void assignParents(tree &t) {
if (!t) return;
if (t->leftChild) {
t->leftChild->parent = t;
t->leftChild->state = 0;
}
if (t->rightChild) {
t->rightChild->parent = t;
t->rightChild->state = 1;
}
assignParents(t->leftChild);
assignParents(t->rightChild);
}
void Print(tree t){
if(!t)
return;
push(t);
Print(t->leftChild);
cout << t->value << " ";
Print(t->rightChild);
}
int N, Q;
int type, x, l, r;
tree t = NULL;
tree nodes[MAX];
int main() {
srand(unsigned(time(NULL)));
scanf("%d%d", &N, &Q);
for(int i = 1; i <= N; i ++){
nodes[i] = Initialize(i);
Insert(t, nodes[i], i);
}
assignParents(t);
while (Q --){
//Print(t); cout << endl;
scanf("%d", &type);
if (type == 1) {
scanf("%d%d", &l, &r);
Reverse(t, l, r);
}
else if(type == 2) {
scanf("%d", &x);
printf("%d\n", Kth_element(t, x));
}
else {
scanf("%d", &x);
printf("%d\n", positionOfElement(nodes[x]));
}
}
return 0;
}