题解:P15992 [PA 2026] 原题加强 2 / Wersja dla profesjonalistów 2
神秘,但是非常好玩!孩子很喜欢!
令跳跃步长为
考虑静态问题,有观察:
-
令
s 是质数,且k < s 永远不劣。显然。
-
设当前
a_i = 1 的i 集合为S ,那么答案至少为\lceil\frac{|S|}{2}\rceil 。证明考虑取
m = 2 。
考虑随机化,随机取两个数
把随机化去掉,考虑对
考虑带修,进行人类智慧:考虑设一个阈值
因为我们带修了,所以
类似上面的思路,我们按每
还是对每个组,两两作差取其质因数,总贡献是
// Think TWICE, code ONCE
#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline ll Read() {
int sig = 1; ll num = 0; char c = getchar();
while(!isdigit(c)) { if(c == '-') sig = -1; c = getchar(); }
while(isdigit(c)) num = (num << 3) + (num << 1) + (c ^ 48), c = getchar();
return num * sig;
}
void Write(ll x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) Write(x / 10);
putchar((x % 10) ^ 48);
}
const int N = 10000005, M = 1000005;
int n, m, cnt, p[M], c[N];
bitset<N> a, b;
int cntp, prime[N], minp[N], to[N];
set<int> st;
void Get() {
int i, j;
for(i = 2; i <= n; i++) {
if(!b[i]) prime[++cntp] = i, minp[i] = i, to[i] = 1;
for(j = 1; j <= cntp && prime[j] * i <= n; j++) {
b[prime[j] * i] = true, minp[prime[j] * i] = prime[j];
if(i % prime[j] == 0) { to[prime[j] * i] = to[i]; break; }
to[prime[j] * i] = i;
}
}
}
int MEM[N * 6], X;
int *t[140], *ct[140];
int maxn[140], hmaxn[140];
int _plist[M * 6], plist[140], s[M];
int Add(int siz, int x, int y) {
int i, ans = 0;
for(i = 0; i < siz; i++) {
int &val = t[i][x % plist[i]];
ct[i][val]--, val += y, ct[i][val]++;
if(ct[i][maxn[i] + 1]) {
if(maxn[i] == hmaxn[i]) ct[i][hmaxn[i] + 2] = 0, hmaxn[i]++;
maxn[i]++;
}
else if(!ct[i][maxn[i]]) maxn[i]--;
ans = max(ans, maxn[i]);
// for(int j = 0; j < ct[i].size(); j++) cerr << ct[i][j] << ' ';
// cerr << endl;
}
return ans;
}
void Solve(int l, int r) {
int i, j, k, cnts = 0, _cntplist = 0, siz = 0;
for(auto v : st) s[cnts++] = v;
for(i = 0; i < cnt; i += 6) for(j = i; j < min(cnt, i + 6); j++) for(k = j + 1; k < min(cnt, i + 6); k++) {
int x = abs(s[j] - s[k]);
while(x > 1) {
if(!b[minp[x]]) b[minp[x]] = true, _plist[_cntplist++] = minp[x];
c[minp[x]]++, x = to[x];
}
}
for(i = 0; i < _cntplist; i++) {
int v = _plist[i];
if(c[v] >= (cnt + 5) / 6) plist[siz++] = v;
b[v] = c[v] = 0;
}
// sort(plist.begin(), plist.end());
int ans = 0; X = 0;
for(i = 0; i < siz; i++) {
t[i] = MEM + X, X += plist[i];
ct[i] = MEM + X, X += cnt + r - l + 5;
maxn[i] = hmaxn[i] = 0, ct[i][0] = ct[i][1] = 0;
for(j = 0; j < plist[i]; j++) t[i][j] = 0;
ct[i][0] = plist[i];
}
for(i = 0; i < cnt; i++) ans = Add(siz, s[i], 1);
Write(ans), putchar('\n');
for(i = l + 1; i <= r; i++) {
if(a[p[i]]) cnt--, st.erase(p[i]), ans = Add(siz, p[i], -1), a[p[i]] = 0;
else cnt++, st.emplace(p[i]), ans = Add(siz, p[i], 1), a[p[i]] = 1;
Write(ans), putchar('\n');
}
}
int main() {
// freopen("F.in", "r", stdin), freopen("F.out", "w", stdout);
int i; n = Read(), m = Read(), Get();
for(i = 1; i <= m; i++) p[i] = Read();
for(i = 1; i <= m; i++) {
if(a[p[i]]) cnt--, st.erase(p[i]), a[p[i]] = 0;
else cnt++, st.emplace(p[i]), a[p[i]] = 1;
if(cnt < 3) Write(cnt - (cnt == 2 && (*st.rbegin() - *st.begin()) == 1)), putchar('\n');
else { int r = min(m, i + cnt / 3); Solve(i, r), i = r; }
}
}