-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathrange-xor-queries-with-subarray-reversals.cpp
134 lines (119 loc) · 3.29 KB
/
range-xor-queries-with-subarray-reversals.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
// Time: O(n + qlogn)
// Space: O(n)
// template from: https://cp-algorithms.com/data_structures/treap.html
using pTreapNode = struct TreapNode *;
struct TreapNode {
int prior, value, cnt;
int xor_sum; // added
bool rev;
pTreapNode l, r;
TreapNode (int v) : value(v), prior(rand()), cnt(1), xor_sum(v), rev(false), l(nullptr), r(nullptr) {} // added
};
int cnt(pTreapNode t) {
return t ? t->cnt : 0;
}
int xor_sum(pTreapNode t) { // added
return t ? t->xor_sum : 0;
}
void upd_cnt(pTreapNode t) {
if (t) {
t->cnt = cnt(t->l) + cnt(t->r) + 1;
t->xor_sum = t->value ^ xor_sum(t->l) ^ xor_sum(t->r); // added
}
}
void push(pTreapNode t) {
if (t && t->rev) {
t->rev = false;
swap(t->l, t->r);
if (t->l) t->l->rev ^= true;
if (t->r) t->r->rev ^= true;
}
}
void merge(pTreapNode& t, pTreapNode l, pTreapNode r) {
push(l);
push(r);
if (!l || !r)
t = l ? l : r;
else if (l->prior > r->prior)
merge(l->r, l->r, r), t = l;
else
merge(r->l, l, r->l), t = r;
upd_cnt(t);
}
void split(pTreapNode t, pTreapNode& l, pTreapNode& r, int key, int add = 0) {
if (!t)
return void(l = r = 0);
push(t);
int cur_key = add + cnt(t->l);
if (key <= cur_key)
split(t->l, l, t->l, key, add), r = t;
else
split(t->r, t->r, r, key, add + 1 + cnt(t->l)), l = t;
upd_cnt(t);
}
void reverse(pTreapNode t, int l, int r) {
pTreapNode t1, t2, t3;
split(t, t1, t2, l);
split(t2, t2, t3, r - l + 1);
t2->rev ^= true;
merge(t, t1, t2);
merge(t, t, t3);
}
void heapify(pTreapNode t) {
if (!t) return;
pTreapNode max = t;
if (t->l && t->l->prior > max->prior)
max = t->l;
if (t->r && t->r->prior > max->prior)
max = t->r;
if (max != t) {
swap(t->prior, max->prior);
heapify(max);
}
}
pTreapNode build(const vector<int>& a, int i, int n) {
if (n == 0) return nullptr;
int mid = n / 2;
auto t = new TreapNode(a[i + mid]);
t->l = build(a, i, mid);
t->r = build(a, i + mid + 1, n - mid - 1);
heapify(t);
upd_cnt(t);
return t;
}
// treap
class Solution {
public:
vector<int> getResults(vector<int>& nums, vector<vector<int>>& queries) {
pTreapNode root = build(nums, 0, size(nums));
const auto& update = [&](int index, int value) {
pTreapNode left, mid, right;
split(root, left, mid, index);
split(mid, mid, right, 1);
mid->value = value;
upd_cnt(mid);
merge(root, left, mid);
merge(root, root, right);
};
const auto& query = [&](int left, int right) {
pTreapNode t1, t2, t3;
split(root, t1, t2, left);
split(t2, t2, t3, right - left + 1);
int result = xor_sum(t2);
merge(root, t1, t2);
merge(root, root, t3);
return result;
};
vector<int> result;
for (const auto& q : queries) {
if (q[0] == 1) {
update(q[1], q[2]);
} else if (q[0] == 2) {
result.emplace_back(query(q[1], q[2]));
} else if (q[0] == 3) {
reverse(root, q[1], q[2]);
}
}
return result;
}
};