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
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
static const int MAX_BITS = 19; // supports values up to 2^19-1 >= 500000
static const int MAX_NODES = 10500000; // ~ (max inserts) * (MAX_BITS+1) with margin
int child0[MAX_NODES];
int child1[MAX_NODES];
int cntNode[MAX_NODES];
int nodeCount = 0;
inline int cloneNode(int from) {
int id = ++nodeCount;
child0[id] = child0[from];
child1[id] = child1[from];
cntNode[id] = cntNode[from];
return id;
}
int insertValue(int oldRoot, int value) {
int newRoot = cloneNode(oldRoot);
cntNode[newRoot]++;
int curNew = newRoot;
int curOld = oldRoot;
for (int bit = MAX_BITS - 1; bit >= 0; --bit) {
int b = (value >> bit) & 1;
int nextOld = (b == 0 ? child0[curOld] : child1[curOld]);
int nextNew = cloneNode(nextOld);
cntNode[nextNew]++;
if (b == 0) child0[curNew] = nextNew;
else child1[curNew] = nextNew;
curNew = nextNew;
curOld = nextOld;
}
return newRoot;
}
inline int getCnt(int node) { return node ? cntNode[node] : 0; }
int queryMaxXorY(int rootR, int rootLminus1, int x) {
int hi = rootR, lo = rootLminus1;
int y = 0;
for (int bit = MAX_BITS - 1; bit >= 0; --bit) {
int xb = (x >> bit) & 1;
int want = 1 - xb;
int hiWant = (want == 0 ? child0[hi] : child1[hi]);
int loWant = (want == 0 ? child0[lo] : child1[lo]);
int haveWant = getCnt(hiWant) - getCnt(loWant);
int go;
if (haveWant > 0) go = want;
else go = 1 - want;
if (go) y |= (1 << bit);
hi = (go == 0 ? child0[hi] : child1[hi]);
lo = (go == 0 ? child0[lo] : child1[lo]);
}
return y;
}
int queryCountLess(int rootR, int rootLminus1, int k) {
// count of values in (L..R) that are < k
int hi = rootR, lo = rootLminus1;
int res = 0;
for (int bit = MAX_BITS - 1; bit >= 0; --bit) {
int kb = (k >> bit) & 1;
if (kb == 1) {
// add all with 0 at this bit
int hi0 = child0[hi], lo0 = child0[lo];
res += getCnt(hi0) - getCnt(lo0);
hi = child1[hi];
lo = child1[lo];
} else {
hi = child0[hi];
lo = child0[lo];
}
if (!hi && !lo) break;
}
return res;
}
int queryKth(int rootR, int rootLminus1, int k) {
int hi = rootR, lo = rootLminus1;
int y = 0;
for (int bit = MAX_BITS - 1; bit >= 0; --bit) {
int hi0 = child0[hi], lo0 = child0[lo];
int leftCnt = getCnt(hi0) - getCnt(lo0);
if (k <= leftCnt) {
hi = hi0; lo = lo0;
} else {
k -= leftCnt;
y |= (1 << bit);
hi = child1[hi];
lo = child1[lo];
}
}
return y;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int M;
if (!(cin >> M)) return 0;
vector<int> roots(M + 2, 0); // roots[len] = trie root after 'len' appends
int curLen = 0; // current array size
for (int i = 0; i < M; ++i) {
int type; cin >> type;
if (type == 1) {
int x; cin >> x;
roots[curLen + 1] = insertValue(roots[curLen], x);
curLen++;
} else if (type == 2) {
int L, R, x; cin >> L >> R >> x;
int y = queryMaxXorY(roots[R], roots[L - 1], x);
cout << y << '\n';
} else if (type == 3) {
int k; cin >> k;
curLen -= k; // move back to previous version
} else if (type == 4) {
int L, R, x; cin >> L >> R >> x;
int ans = queryCountLess(roots[R], roots[L - 1], x + 1); // <= x
cout << ans << '\n';
} else if (type == 5) {
int L, R, k; cin >> L >> R >> k;
int y = queryKth(roots[R], roots[L - 1], k);
cout << y << '\n';
}
}
return 0;
}
|