-
Notifications
You must be signed in to change notification settings - Fork 93
/
Copy patheven_odd_mo.cpp
123 lines (117 loc) · 3.07 KB
/
even_odd_mo.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
// Credits: Aeren
// https://codeforces.com/contest/1511/submission/112913505
#include <bits/stdc++.h>
using namespace std;
// Reorder N 2D points with max_x - min_x <= X, max_y - min_y <= Y
// so that sum(abs(xi - x(i+1)) + abs(yi - y(i+1)) is small
// and process queries on the new order.
// N BX inc_x and dec_x calls, X Y / BX inc_y and dec_y calls at max
// set BX = sqrt(X Y / N) to achieve sqrt(X Y N) calls at max
template<int BX>
struct mo_2d{
vector<array<int, 3>> points; // x, y, ind
void insert(int x, int y, int id){
points.push_back({x, y, id});
}
// starting from (0, 0), access each points and execute queries
void solve(auto inc_x, auto dec_x, auto inc_y, auto dec_y, auto process){
auto cmp = [&](const auto &p, const auto &q)->bool{
return p[0] / BX != q[0] / BX ? p < q : p[0] / BX & 1 ? p[1] < q[1] : p[1] > q[1];
};
sort(points.begin(), points.end(), cmp);
int x = 0, y = 0;
for(auto &[qx, qy, id]: points){
while(qx < x) dec_x(), -- x;
while(y < qy) inc_y(), ++ y;
while(x < qx) inc_x(), ++ x;
while(qy < y) dec_y(), -- y;
process(id);
}
}
};
int main(){
cin.tie(0)->sync_with_stdio(0);
cin.exceptions(ios::badbit | ios::failbit);
int n, m;
cin >> n >> m;
vector<int> flag(m);
for(auto i = 0; i < n; ++ i){
int x;
cin >> x, -- x;
flag[x] ^= 1;
}
int qn;
cin >> qn;
mo_2d<int(sqrt(2e5))> mo;
for(auto qi = 0; qi < qn; ++ qi){
int l, r;
cin >> l >> r, -- l;
mo.insert(l, r, qi);
}
int l = 0, r = 0, xor_sum = 0;
const int mx = __lg(m) + 1;
vector<deque<bool>> cnt(mx);
for(auto bit = 0; bit < mx; ++ bit){
cnt[bit].assign(1 << bit, 0);
}
auto inc_x = [&](){
if(flag[l]){
for(auto bit = 0; bit < mx; ++ bit){
cnt[bit].front() ^= true;
}
}
for(auto bit = 0; bit < mx; ++ bit){
xor_sum ^= cnt[bit].front() << bit;
cnt[bit].push_back(cnt[bit].front());
cnt[bit].pop_front();
}
++ l;
};
auto dec_x = [&](){
-- l;
for(auto bit = 0; bit < mx; ++ bit){
xor_sum ^= cnt[bit].back() << bit;
cnt[bit].push_front(cnt[bit].back());
cnt[bit].pop_back();
}
if(flag[l]){
for(auto bit = 0; bit < mx; ++ bit){
cnt[bit][0] ^= true;
}
}
};
auto inc_y = [&](){
if(flag[r]){
int x = r - l;
xor_sum ^= x;
for(auto bit = 0; bit < mx; ++ bit){
cnt[bit][x & (1 << bit) - 1] ^= true;
}
}
++ r;
};
auto dec_y = [&](){
-- r;
if(flag[r]){
int x = r - l;
xor_sum ^= x;
for(auto bit = 0; bit < mx; ++ bit){
cnt[bit][x & (1 << bit) - 1] ^= true;
}
}
};
string res(qn, '?');
auto process = [&](int qi){
res[qi] = 'A' + !xor_sum;
};
mo.solve(inc_x, dec_x, inc_y, dec_y, process);
cout << res << "\n";
return 0;
}
/*
*/
////////////////////////////////////////////////////////////////////////////////////////
// //
// Coded by Aeren //
// //
////////////////////////////////////////////////////////////////////////////////////////