Problem Author: | Mohammad Nasser (MOAGEZA) |
Prepared by: | Mohammad Nasser (MOAGEZA) |
Edited by: | Hasan Saleh (MathModel) |
Həll
Ümumi ideya:
Əgər a_i elementində -da olmayan hər hansı bir bit -dirsə, onda a_i elementi ilə uyğunsuz sayılır — formal olaraq, əgər (a_i \,\&\, \sim k) \neq 0 olarsa, yəni a_i-də elə ən azı bir bit var ki, a_i-də , amma -da -dır. Belə element heç vaxt OR-u -ya bərabər olan bir altmassivin hissəsi ola bilməz, buna görə də o silinməlidir. Hər bir uyğunsuz elementi ilə əvəz edin və onun mövqeyini prefiks cəmi massivi -da qeyd edin ki, \mathit{sum}[r] - \mathit{sum}[l-1] ifadəsi [l, r] aralığında lazım olan silinmələrin sayını versin.
Uyğunsuz elementləri sıfırladıqdan sonra dəyişdirilmiş massiv üzərində aralıq OR sorğularını vaxtda cavablandırmaq üçün sparse table qurun.
Addım 1 — Minimum silinmələr:
Hər bir sol sərhəd üçün elə ən kiçik sağ sərhəd -i ikili axtarışla tapın ki, \mathrm{OR}(i, r) = k olsun. pəncərəsinin dəyəri \mathit{sum}[r] - \mathit{sum}[i-1] olacaq. Bütün uyğun pəncərələr üzrə minimumu götürün:
Əgər heç bir pəncərə OR əldə etmirsə, -1 -1 çıxış verin.
Addım 2 — Maksimum uzunluq:
Hər bir sol sərhəd üçün elə ən böyük sağ sərhəd -i ikili axtarışla tapın ki, aralığındakı silinmələrin sayı -ı aşmasın və \mathrm{OR}(i, r) = k olsun. Alınan altmassivin effektiv uzunluğu (silinmələrdən sonra) (r - i + 1) - \mathit{ans} olacaq. Bütün uyğun pəncərələr üzrə maksimumu götürün:
Həllin işləmə vaxtı hər test faylı üçün \mathcal{O}\!\left(n \log n + \sum n\right)-dir; burada n \log n hissəsi sparse table qurulmasından, qalan hissə isə iki ikili axtarış keçidindən gəlir.
#include <bits/stdc++.h>
#define ll long long
#define rv return void
#define vec vector
#define Moageza ios::sync_with_stdio(false);cout.tie(NULL);cin.tie(NULL);
using namespace std;
const int N = 2e5 + 5;
int n, k, a[N], T[N][22], Log[N];
int merge(int a, int b) { return (a | b); }
void build() {
for (int i = 1; i <= n; i++) T[i][0] = a[i];
for (int pw = 1; (1 << pw) <= n; pw++)
for (int i = 1; i + (1 << pw) - 1 <= n; i++)
T[i][pw] = merge(T[i][pw-1], T[i+(1<<(pw-1))][pw-1]);
}
int query(int l, int r) {
int pw = Log[r - l + 1];
return merge(T[l][pw], T[r-(1<<pw)+1][pw]);
}
void preCount() {
Log[1] = 0;
for (int i = 2; i < N; i++) Log[i] = Log[i >> 1] + 1;
}
void solve() {
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> a[i];
vec<int> sum(n + 1, 0);
for (int i = 1; i <= n; i++) {
bitset<30> f = a[i], s = k;
bool bad = false;
for (int j = 0; j < 30; j++)
if (f[j] && !s[j]) bad = true;
if (bad) { a[i] = 0; sum[i] = 1; }
}
for (int i = 1; i <= n; i++) sum[i] += sum[i-1];
build();
int ans = 1e9, len = 0;
for (int i = 1; i <= n; i++) {
int l = i, r = n;
while (l <= r) {
int mid = (l + r) / 2;
if (query(i, mid) == k) {
ans = min(ans, sum[mid] - sum[i-1]);
r = mid - 1;
} else l = mid + 1;
}
}
if (ans == (int)1e9) rv(cout << "-1 -1");
for (int i = 1; i <= n; i++) {
int l = i, r = n;
while (l <= r) {
int mid = (l + r) / 2;
if (sum[mid] - sum[i-1] <= ans) {
l = mid + 1;
if (query(i, mid) == k)
len = max(len, (mid - i + 1) - ans);
} else r = mid - 1;
}
}
cout << ans << " " << len;
}
signed main() {
Moageza
preCount();
int t; cin >> t;
while (t--) { solve(); cout << "\n"; }
return 0;
}