题目链接:https://codeforces.com/contest/1878/problem/E
题目大意: t 组数据 ,每组给出一个 n 长的 a 序列 ,q 个询问 ,询问 f(l,r) ≥ k 的 最大索引 r ,其中 f(l,r) 表示 a 序列从 l 到 r 的按位与&值。
题目思路: 区间操作,容易想到线段树、树状数组、分块,此题可以用静态的分块操作。题目很裸,在暴力写法基础上二分+分块就能通过此题
#pragma GCC optimize(2)
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define endl '\n'
#define fr first
#define sc second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<ll, ll> pii;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
const ll INF_ = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
ll n, m, k, x, y, l, r, res = 0, sum = 0, ma = 0, ma_r = 0, mi = INF;
ll a[N], st[N], ed[N], belong[N], ans[N], block;
void f(ll l)
{
ll L = l, R = n, mid;
sum = a[l];
for (int i = l + 1; i <= ed[belong[l]]; i++)
sum &= a[i];
while (L <= R) {
mid = (L + R) >> 1;
res = sum;
if (belong[mid] == belong[l]) {
res = a[l];
for (int j = l; j <= mid; j++)
res &= a[j];
} else {
for (int j = belong[l] + 1; j < belong[mid]; j++)
res &= ans[j];
for (int j = st[belong[mid]]; j <= mid; j++)
res &= a[j];
}
if (res >= k) {
ma_r = mid;
L = mid + 1;
} else
R = mid - 1;
}
}
void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
ll q;
cin >> q;
block = (ll)sqrt(n);
for (int i = 1; i <= block; i++) {
st[i] = n / block * (i - 1) + 1;
ed[i] = n / block * i;
}
ed[block] = n;
for (int i = 1; i <= block; i++) {
res = a[st[i]];
belong[st[i]] = i;
for (int j = st[i] + 1; j <= ed[i]; j++) {
belong[j] = i;
res &= a[j];
}
ans[i] = res;
}
while (q--) {
ma_r = -1;
cin >> l >> k;
f(l);
cout << ma_r << " ";
}
cout << endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
// cout.tie(0);
ll _;
cin >> _;
while (_--)
solve();
return 0;
}