Problem Author: | Mohammad Nasser (MOAGEZA) |
Prepared by: | Mohammad Nasser (MOAGEZA) |
Edited by: | Hasan Saleh (MathModel) |
Solution
General Idea:
An element a_i is incompatible with if it has a bit set that does not — formally, if (a_i \,\&\, \sim k) \neq 0, i.e. a_i has at least one bit that is in a_i but in . Such an element can never be part of a subarray whose OR equals , so it must be removed. Replace every incompatible element with and record its position in a prefix sum array , so that \mathit{sum}[r] - \mathit{sum}[l-1] gives the number of removals needed in the range [l, r].
After zeroing incompatible elements, build a sparse table on the modified array to answer range OR queries in .
Step 1 — Minimum removals:
For each left endpoint , binary search for the smallest right endpoint such that \mathrm{OR}(i, r) = k. The cost of the window is \mathit{sum}[r] - \mathit{sum}[i-1]. Take the minimum over all valid windows:
If no window ever achieves OR , output -1 -1.
Step 2 — Maximum length:
For each left endpoint , binary search for the largest right endpoint such that the number of removals in does not exceed and \mathrm{OR}(i, r) = k. The effective length of the resulting subarray (after removals) is (r - i + 1) - \mathit{ans}. Take the maximum over all valid windows:
The solution runs in \mathcal{O}\!\left(n \log n + \sum n\right) time per test file, where the n \log n term comes from the sparse table construction and the two binary search passes.
#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;
}