Codeforces Round 900 (Div. 3)
E
题意:
给你一个数组a, 定义f(l, r) = a[l] & a[l + 1]...&a[r],现在给你q次询问,每次给你一个l,k,求一个最大的r使得f(l, r) >= k
思路:
先拆位计算,就把原数组看成一个二进制的二维数组n行30列,这样的话可以发现对于一个区间[l, r]来说,只有当某一列在这段区间内全为一才能有贡献
所以要先求一下每一列的前缀和,这样就可以O(1)判断某一段是不是全一,那样每次查询我们就二分找到最后一个符合条件的(如果x符合,那么小于x的肯定也符合因为都是一)
inline void solve()
{
int n; cin >> n;
std::vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
vector<array<int, 30>> s(n + 1);
for (int i = 1; i <= n; i++)
for (int j = 0; j < 30; j++)
{
s[i][j] = s[i - 1][j];
if (a[i] >> j & 1) s[i][j]++;
}
int q; cin >> q;
while (q--)
{
int t, k; cin >> t >> k;
int l = t, r = n;
auto check = [&](int l, int r)
{
LL ans = 0;
for (int i = 0; i < 30; i++)
if (s[r][i] - s[l - 1][i] == r - l + 1) ans += 1 << i;
return ans >= k;
};
while (l < r)
{
int mid = (l + r + 1) / 2;
if (check(t, mid)) l = mid;
else r = mid - 1;
}
if (check(t, l)) cout << l << ' ';
else cout << -1 << ' ';
}
cout << endl;
}

浙公网安备 33010602011771号