意:给n个数的数组和m次询问,每次询问给出l,k;要求找到一个最大的r使得a[l]&a[l+1]&...&a[r]>=k;若不存在输出-1
思路:数越多时,&的结果会越小;找到存在一段区间[l,r]某些二进制j位上在这连续的一段都是1;前缀和算下每一个数的二进制位的1;
每次询问时,a[l]<k的情况说明>k的位置都是0,后面也不可能变成1;
a[l]>=k时:用二分找到一个位置(因为&的结果是递减的)a[l]的所有1的二进制位上存在几个使得[l,r]的一段区间中二进制位也都是1
int a[N], cnt[N][32];
int n, m, k;
vector<int>v;
bool check(int l, int r)
{
int len = r - l + 1;
int ans = 0;
for (auto j : v)
{
int s = cnt[r][j] - cnt[l - 1][j];
if (s == len)ans += 1ll << j;
}
if (ans < k)return false;
return true;
}
void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
for (int j = 0; j < 32; j++)
{
int ans = a[i] >> j;
if (ans & 1)cnt[i][j] = cnt[i - 1][j] + 1;
else cnt[i][j] = cnt[i - 1][j];
}
}
cin >> m;
for (int i = 1; i <= m; i++)
{
int l;
cin >> l >> k;
if (a[l] < k)cout << "-1 ";
else
{
v.clear();
for (int j = 0; j < 32; j++)
if (a[l] >> j & 1)v.push_back(j);
int L = l, R = n;
while (L<R)
{
int mid = L+R + 1>> 1;
if (check(l, mid))L = mid;
else R = mid - 1;
}
cout << L << " ";
}
}
cout << endl;
}