#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e7 + 5;
const int SMALL_PRIMES = 1200;
int sieve[MAXN], pos_in_active[MAXN];
bitset <MAXN> is_active;
vector <int> active_stones, small_primes;
const int ITER = 65;
const int HITS = 3;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// https://codeforces.com/blog/entry/21853
struct HASH {
size_t operator()(const pair <int, int> &x) const {
return hash<long long>()(((long long)x.first)^(((long long)x.second)<<32));
}
};
int main() {
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n, q;
cin >> n >> q;
for (int i = 2; i <= n; i++) {
if (sieve[i] == 0) {
if (i <= SMALL_PRIMES) {
small_primes.push_back(i);
}
for (int j = i; j <= n; j += i) {
sieve[j] = i;
}
}
}
if (n == 1) {
small_primes.push_back(2);
sieve[2] = 2;
}
vector <int> max_cnt(small_primes.size() + 1, 0);
vector <vector <int>> cnt(small_primes.size() + 1), freq(small_primes.size() + 1);
for (int i = 0; i < small_primes.size(); i++) {
int p = small_primes[i];
cnt[i].resize(p, 0);
freq[i].resize(n / p + 2, 0);
freq[i][0] = p;
}
int prv_ans = 0;
while (q--) {
int x;
cin >> x;
bool add = (!is_active[x]);
int ans = 0;
if (add) ans = prv_ans;
if (is_active[x]) {
is_active[x] = false;
int idx = pos_in_active[x];
int last_val = active_stones.back();
active_stones[idx] = last_val;
pos_in_active[last_val] = idx;
active_stones.pop_back();
for (int i = 0; i < small_primes.size(); i++) {
int p = small_primes[i];
int r = x % p;
freq[i][cnt[i][r]]--;
if (cnt[i][r] == max_cnt[i] && freq[i][cnt[i][r]] == 0) {
max_cnt[i]--;
}
cnt[i][r]--;
freq[i][cnt[i][r]]++;
}
} else {
is_active[x] = true;
pos_in_active[x] = active_stones.size();
active_stones.push_back(x);
for (int i = 0; i < small_primes.size(); i++) {
int p = small_primes[i];
int r = x % p;
freq[i][cnt[i][r]]--;
cnt[i][r]++;
freq[i][cnt[i][r]]++;
if (cnt[i][r] > max_cnt[i]) {
max_cnt[i] = cnt[i][r];
}
}
}
for (int i = 0; i < small_primes.size(); i++) {
if (max_cnt[i] > ans) ans = max_cnt[i];
}
int S = active_stones.size();
if (((add && prv_ans + 1 != ans) || (!add && prv_ans != ans)) && S >= 2 && ans != 0 && n / ans >= SMALL_PRIMES && ans != S) {
unordered_map <pair <int, int>, int, HASH> candidates;
// map <pair <int, int>, int> candidates;
for (int iter = 0; iter < ITER; iter++) {
int u = active_stones[rng() % S];
int v = active_stones[rng() % S];
if (add) v = x;
int dist = abs(u - v);
while (dist > SMALL_PRIMES) {
int p = sieve[dist];
if (SMALL_PRIMES < p && p <= n / ans) {
candidates[{p, u % p}]++;
}
while (dist % p == 0) dist /= p;
}
}
for (auto [cand, hits] : candidates) if (hits >= HITS && cand.first <= n / ans) {
auto [p, r] = cand;
int cnt = 0;
if (n / p + 1 <= S) {
for (int v = r; v <= n; v += p) {
if (is_active[v]) cnt++;
}
} else {
for (auto stone : active_stones) {
if (stone % p == r) cnt++;
}
}
if (cnt > ans) ans = cnt;
}
}
prv_ans = ans;
cout << ans << "\n";
}
}
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 | #include <bits/stdc++.h> using namespace std; const int MAXN = 1e7 + 5; const int SMALL_PRIMES = 1200; int sieve[MAXN], pos_in_active[MAXN]; bitset <MAXN> is_active; vector <int> active_stones, small_primes; const int ITER = 65; const int HITS = 3; mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); // https://codeforces.com/blog/entry/21853 struct HASH { size_t operator()(const pair <int, int> &x) const { return hash<long long>()(((long long)x.first)^(((long long)x.second)<<32)); } }; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n, q; cin >> n >> q; for (int i = 2; i <= n; i++) { if (sieve[i] == 0) { if (i <= SMALL_PRIMES) { small_primes.push_back(i); } for (int j = i; j <= n; j += i) { sieve[j] = i; } } } if (n == 1) { small_primes.push_back(2); sieve[2] = 2; } vector <int> max_cnt(small_primes.size() + 1, 0); vector <vector <int>> cnt(small_primes.size() + 1), freq(small_primes.size() + 1); for (int i = 0; i < small_primes.size(); i++) { int p = small_primes[i]; cnt[i].resize(p, 0); freq[i].resize(n / p + 2, 0); freq[i][0] = p; } int prv_ans = 0; while (q--) { int x; cin >> x; bool add = (!is_active[x]); int ans = 0; if (add) ans = prv_ans; if (is_active[x]) { is_active[x] = false; int idx = pos_in_active[x]; int last_val = active_stones.back(); active_stones[idx] = last_val; pos_in_active[last_val] = idx; active_stones.pop_back(); for (int i = 0; i < small_primes.size(); i++) { int p = small_primes[i]; int r = x % p; freq[i][cnt[i][r]]--; if (cnt[i][r] == max_cnt[i] && freq[i][cnt[i][r]] == 0) { max_cnt[i]--; } cnt[i][r]--; freq[i][cnt[i][r]]++; } } else { is_active[x] = true; pos_in_active[x] = active_stones.size(); active_stones.push_back(x); for (int i = 0; i < small_primes.size(); i++) { int p = small_primes[i]; int r = x % p; freq[i][cnt[i][r]]--; cnt[i][r]++; freq[i][cnt[i][r]]++; if (cnt[i][r] > max_cnt[i]) { max_cnt[i] = cnt[i][r]; } } } for (int i = 0; i < small_primes.size(); i++) { if (max_cnt[i] > ans) ans = max_cnt[i]; } int S = active_stones.size(); if (((add && prv_ans + 1 != ans) || (!add && prv_ans != ans)) && S >= 2 && ans != 0 && n / ans >= SMALL_PRIMES && ans != S) { unordered_map <pair <int, int>, int, HASH> candidates; // map <pair <int, int>, int> candidates; for (int iter = 0; iter < ITER; iter++) { int u = active_stones[rng() % S]; int v = active_stones[rng() % S]; if (add) v = x; int dist = abs(u - v); while (dist > SMALL_PRIMES) { int p = sieve[dist]; if (SMALL_PRIMES < p && p <= n / ans) { candidates[{p, u % p}]++; } while (dist % p == 0) dist /= p; } } for (auto [cand, hits] : candidates) if (hits >= HITS && cand.first <= n / ans) { auto [p, r] = cand; int cnt = 0; if (n / p + 1 <= S) { for (int v = r; v <= n; v += p) { if (is_active[v]) cnt++; } } else { for (auto stone : active_stones) { if (stone % p == r) cnt++; } } if (cnt > ans) ans = cnt; } } prv_ans = ans; cout << ans << "\n"; } } |
English