fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4.  
  5. using namespace std;
  6.  
  7. const int B = 600; // Optymalny próg podziału (do ewentualnego dostrojenia)
  8. int cnt[B + 1][B + 1];
  9. int max_val[B + 1];
  10. int global_max_small = 0;
  11.  
  12. int main() {
  13. ios_base::sync_with_stdio(false);
  14. cin.tie(NULL);
  15.  
  16. int n, q;
  17. if (!(cin >> n >> q)) return 0;
  18.  
  19. vector<bool> A(n + 1, false);
  20. int C = 0; // Aktualna liczba kamieni na planszy
  21.  
  22. for (int i = 0; i < q; ++i) {
  23. int x;
  24. cin >> x;
  25.  
  26. bool is_add = !A[x];
  27. A[x] = !A[x]; // Zmiana stanu pola
  28.  
  29. if (is_add) {
  30. C++;
  31. for (int K = 2; K <= B; ++K) {
  32. int mod = x % K;
  33. cnt[K][mod]++;
  34. if (cnt[K][mod] > max_val[K]) {
  35. max_val[K] = cnt[K][mod];
  36. }
  37. }
  38. } else {
  39. C--;
  40. for (int K = 2; K <= B; ++K) {
  41. int mod = x % K;
  42. cnt[K][mod]--;
  43. // Leniwa aktualizacja maksimów przy usuwaniu dla przyspieszenia
  44. }
  45. }
  46.  
  47. // 1. Znajdź najlepszy wynik dla małych K (z uwzględnieniem leniwego usuwania)
  48. global_max_small = 0;
  49. for (int K = 2; K <= B; ++K) {
  50. // Jeśli zarejestrowane maksimum mogło spaść z powodu usunięcia, przelicz
  51. if (!is_add && max_val[K] > 0) {
  52. int true_max = 0;
  53. for (int m = 0; m < K; ++m) {
  54. if (cnt[K][m] > true_max) {
  55. true_max = cnt[K][m];
  56. }
  57. }
  58. max_val[K] = true_max;
  59. }
  60. if (max_val[K] > global_max_small) {
  61. global_max_small = max_val[K];
  62. }
  63. }
  64.  
  65. int current_best = global_max_small;
  66.  
  67. // 2. Jeśli mamy mało kamieni i duże K ma szansę pobić current_best
  68. // Szukamy tylko do momentu, gdzie n / K > current_best
  69. int limit_K = min(n, n / max(1, current_best));
  70.  
  71. if (limit_K > B) {
  72. // Ponieważ szukamy wyniku dla dużych K (które robią duże "skoki"),
  73. // iterujemy na bieżąco po planszy dla tych kandydatów.
  74. for (int K = B + 1; K <= limit_K; ++K) {
  75. // Przeszukiwanie kroków
  76. // (W pełnym rozwiązaniu turniejowym w tym miejscu stosuje się dodatkową
  77. // kompresję niepustych pol dla bardzo małego C)
  78. int local_max = 0;
  79. for (int start = 1; start <= min(K, n); ++start) {
  80. int current_score = 0;
  81. for (int pos = start; pos <= n; pos += K) {
  82. if (A[pos]) current_score++;
  83. }
  84. if (current_score > local_max) {
  85. local_max = current_score;
  86. }
  87. }
  88. if (local_max > current_best) {
  89. current_best = local_max;
  90. }
  91. }
  92. }
  93.  
  94. cout << current_best << "\n";
  95. }
  96.  
  97. return 0;
  98. }
Success #stdin #stdout 0.01s 5308KB
stdin
9 10
1
4
8
2
3
8
6
9
2
4
stdout
1
2
2
3
3
2
3
3
3
3