#include <bits/stdc++.h>
#define pi pair<int, int>
using namespace std;
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n, q;
cin >> n >> q;
vector<int> input(q);
vector<int> curr_in(n + 1);
int d = 0;
int max_d = 0;
int sum_d = 0;
for (auto &x : input) {
cin >> x;
if (curr_in[x])
d--;
else
d++;
curr_in[x] ^= 1;
max_d = max(d, max_d);
sum_d += d;
}
/*
O(30*sum_d*8) probabilistic. Chance of mistake 0.1%
//30 tries, and each number has at most 8 prime divisors
*/
auto probabilistic = [&]() {
vector<int> sieve(n + 1, 1);
vector<int> primes;
vector<vector<int>> prime_divs(n + 1, vector<int>(1));
prime_divs[0] = prime_divs[1] = vector<int>();
for (int i = 2; i <= n; i++) {
if (!sieve[i])
continue;
sieve[i] = true;
prime_divs[i][0] = i;
primes.push_back(i);
for (long long j = (long long)i * i; j <= n; j += i) {
sieve[j] = false;
prime_divs[j][0] = i;
}
}
for (int k = 2; k <= n; k++) {
if (sieve[k])
continue;
int num = k;
int q = prime_divs[k][0];
while (num % q == 0)
num /= q;
for (auto prim : prime_divs[num]) {
prime_divs[k].push_back(prim);
}
}
d = 0;
vector<pi> div_counts(n + 1);
list<int> currently_in;
vector<pair<int, list<int>::iterator>> is_in(n + 1);
std::random_device rd; // a seed source for the random number engine
std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> distrib(0, INT_MAX);
// idk the complexity of this constructor so just in case instead of doing
// this for every d I'm just gonna take modulo each time cause i dont have
// the time rn
for (auto [generation, x] : views::enumerate(input)) {
if (is_in[x].first == 0) {
currently_in.push_back(x);
is_in[x] = {x, prev(currently_in.end())};
d++;
} else {
currently_in.erase(is_in[x].second);
is_in[x].first = 0;
d--;
}
vector<int> current{currently_in.begin(), currently_in.end()};
int res = (d + 1) / 2;
int minigen = 30 * generation;
for (int _ = 0; _ < 30; _++) {
int checked = distrib(gen) % d;
for (int i = 0; i < d; i++) {
int num = abs(current[i] - current[checked]);
for (auto prim : prime_divs[num]) {
if (div_counts[prim].second != minigen) {
div_counts[prim] = {0, minigen};
}
div_counts[prim].first++;
res = max(res, div_counts[prim].first + 1);
//+1 bc of zero
}
}
minigen++;
}
cout << res << '\n';
}
};
auto basic = [&]() {
for (int i = 0; i < curr_in.size(); i++)
curr_in[i] = 0;
vector<bool> sieve(n + 1, 1);
vector<int> primes;
for (int i = 2; i <= n; i++) {
if (!sieve[i])
continue;
sieve[i] = true;
primes.push_back(i);
for (int j = i * i; j <= n; j += i)
sieve[j] = false;
}
const int pn = primes.size();
vector<vector<set<int>>> current_state(primes.size());
for (int i = 0; i < pn; i++) {
current_state[i].resize(primes[i]);
}
multiset<int> results;
for (auto &x : input) {
bool is_in = curr_in[x];
curr_in[x] ^= 1;
auto update = [&](int i) {
auto to_change =
results.find((int)current_state[i][x % primes[i]].size());
if (is_in) {
current_state[i][x % primes[i]].erase(x);
results.insert(-1 + *to_change);
results.erase(to_change);
} else {
current_state[i][x % primes[i]].insert(x);
int num = 1;
if (to_change != results.end()) {
num = 1 + *to_change;
results.erase(to_change);
}
results.insert(num);
}
};
for (int i = 0; i < primes.size(); i++) {
update(i);
}
cout << (results.empty() ? 0 : *prev(results.end())) << '\n';
}
};
if(n <= 100 && q <= 1000){
basic();
return 0;
}
if (sum_d <= 1000000) {
probabilistic();
return 0;
}
if (n <= 8000 && n * q <= (long long)8000 * 1000) {
basic();
return 0;
}
if (sum_d <= 1900000) {
probabilistic();
return 0;
}
if (n <= 9000 && n * q <= (long long)9000 * 13000) {
basic();
return 0;
}
if(sum_d <= 2100000){
probabilistic();
return 0;
}
basic();
return 0;
}
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 | #include <bits/stdc++.h> #define pi pair<int, int> using namespace std; signed main() { ios_base::sync_with_stdio(0); cin.tie(0); int n, q; cin >> n >> q; vector<int> input(q); vector<int> curr_in(n + 1); int d = 0; int max_d = 0; int sum_d = 0; for (auto &x : input) { cin >> x; if (curr_in[x]) d--; else d++; curr_in[x] ^= 1; max_d = max(d, max_d); sum_d += d; } /* O(30*sum_d*8) probabilistic. Chance of mistake 0.1% //30 tries, and each number has at most 8 prime divisors */ auto probabilistic = [&]() { vector<int> sieve(n + 1, 1); vector<int> primes; vector<vector<int>> prime_divs(n + 1, vector<int>(1)); prime_divs[0] = prime_divs[1] = vector<int>(); for (int i = 2; i <= n; i++) { if (!sieve[i]) continue; sieve[i] = true; prime_divs[i][0] = i; primes.push_back(i); for (long long j = (long long)i * i; j <= n; j += i) { sieve[j] = false; prime_divs[j][0] = i; } } for (int k = 2; k <= n; k++) { if (sieve[k]) continue; int num = k; int q = prime_divs[k][0]; while (num % q == 0) num /= q; for (auto prim : prime_divs[num]) { prime_divs[k].push_back(prim); } } d = 0; vector<pi> div_counts(n + 1); list<int> currently_in; vector<pair<int, list<int>::iterator>> is_in(n + 1); std::random_device rd; // a seed source for the random number engine std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd() std::uniform_int_distribution<> distrib(0, INT_MAX); // idk the complexity of this constructor so just in case instead of doing // this for every d I'm just gonna take modulo each time cause i dont have // the time rn for (auto [generation, x] : views::enumerate(input)) { if (is_in[x].first == 0) { currently_in.push_back(x); is_in[x] = {x, prev(currently_in.end())}; d++; } else { currently_in.erase(is_in[x].second); is_in[x].first = 0; d--; } vector<int> current{currently_in.begin(), currently_in.end()}; int res = (d + 1) / 2; int minigen = 30 * generation; for (int _ = 0; _ < 30; _++) { int checked = distrib(gen) % d; for (int i = 0; i < d; i++) { int num = abs(current[i] - current[checked]); for (auto prim : prime_divs[num]) { if (div_counts[prim].second != minigen) { div_counts[prim] = {0, minigen}; } div_counts[prim].first++; res = max(res, div_counts[prim].first + 1); //+1 bc of zero } } minigen++; } cout << res << '\n'; } }; auto basic = [&]() { for (int i = 0; i < curr_in.size(); i++) curr_in[i] = 0; vector<bool> sieve(n + 1, 1); vector<int> primes; for (int i = 2; i <= n; i++) { if (!sieve[i]) continue; sieve[i] = true; primes.push_back(i); for (int j = i * i; j <= n; j += i) sieve[j] = false; } const int pn = primes.size(); vector<vector<set<int>>> current_state(primes.size()); for (int i = 0; i < pn; i++) { current_state[i].resize(primes[i]); } multiset<int> results; for (auto &x : input) { bool is_in = curr_in[x]; curr_in[x] ^= 1; auto update = [&](int i) { auto to_change = results.find((int)current_state[i][x % primes[i]].size()); if (is_in) { current_state[i][x % primes[i]].erase(x); results.insert(-1 + *to_change); results.erase(to_change); } else { current_state[i][x % primes[i]].insert(x); int num = 1; if (to_change != results.end()) { num = 1 + *to_change; results.erase(to_change); } results.insert(num); } }; for (int i = 0; i < primes.size(); i++) { update(i); } cout << (results.empty() ? 0 : *prev(results.end())) << '\n'; } }; if(n <= 100 && q <= 1000){ basic(); return 0; } if (sum_d <= 1000000) { probabilistic(); return 0; } if (n <= 8000 && n * q <= (long long)8000 * 1000) { basic(); return 0; } if (sum_d <= 1900000) { probabilistic(); return 0; } if (n <= 9000 && n * q <= (long long)9000 * 13000) { basic(); return 0; } if(sum_d <= 2100000){ probabilistic(); return 0; } basic(); return 0; } |
English