Iva and Pav are a famous Serbian competitive programming couple. In Serbia, they call Pav "papuca" and that's why he will make all of Iva's wishes come true.
Iva gave Pav an array a of n elements.
Let's define f(l,r)=al & al+1 &…& ar (here && denotes the bitwise AND operation).
Note that f(l,r)is not defined when l>r.
Iva also gave Pav q queries.
Each query consists of 2 numbers, k and l, and she wants Pav to find the largest index r (l≤r≤n), such that f(l,r)≥k.
Pav wants to solve this problem fast because he doesn't want to upset Iva. He needs your help.
Input
The first line contains a single integer t (1≤t≤10^4) — the number of test cases.
The first line of each test case contains a single integer n (1≤n≤2⋅10^5) — the length of array a.
The second line of each test case contains n integers a1,a2,…,an (1≤ai≤10^9) — the elements of array a.
The third line of each test case contains a single integer q (1≤q≤10^5) — the number of queries Iva gave Pav.
The next q lines of each test case contains two numbers, l and k (1≤l≤n, 1≤k≤10^9) — the left bound for the subsegment, and the integer k described in statement.
It is guaranteed that the sum of n over all test cases does not exceed 2⋅10^5. Also, it is guaranteed that the sum of q over all test cases does not exceed 2⋅10^5.
Output
For each query output maximal index r (l≤r≤n) such that al & al+1 &…& ar ≥ k.
If such r doesn't exist, output −1.
input
- 3
- 5
- 15 14 17 42 34
- 3
- 1 7
- 2 15
- 4 5
- 5
- 7 5 3 1 7
- 4
- 1 7
- 5 7
- 2 3
- 2 2
- 7
- 19 20 15 12 21 7 11
- 4
- 1 15
- 4 4
- 7 12
- 5 7
output
- 2 -1 5
- 1 5 2 2
- 2 6 -1 5
题意:给定n个数,定义f(l,r)=al & al+1 &…& ar,即区间按位与的值,给定q个询问,给定l,k,问最远的r满足f(l,r)>=k,如果不存在输出-1.
解析:根据按位与的性质可知,全一才为1,否则为0,因此,一段区间内部肯定是单调的,因此可以二分,我们可以记录一下前i个数,二进制是j的个数的前缀和,对于每个询问二分>=k的右边界即可。
- #include
- using namespace std;
- const int N=2e5+5;
- int sum[N][35];//前i个数,二进制是j的个数
- bool check(int r,int l,int k)
- {
- int s=0;//总和
- for(int i=1;i<=32;i++)
- {
- if(sum[r][i]-sum[l-1][i]==r-l+1)//全1才是1
- {
- s+=1<<(i-1);
- if(s>=k) return true;//满足直接退出即可
- }
- }
- return false;
- }
- void solve()
- {
- int n;
- scanf("%d",&n);
- for(int i=1;i<=n;i++)
- {
- int x,cnt=0;
- scanf("%d",&x);
- while(x)
- {
- sum[i][++cnt]=x%2;//
- x/=2;
- }
- }
- //累加前缀和
- for(int i=1;i<=n;i++)
- for(int j=1;j<=32;j++) sum[i][j]+=sum[i-1][j];
- int q;
- scanf("%d",&q);
- while(q--)
- {
- int l,k,ans=-1;
- scanf("%d%d",&l,&k);
- int L=l,R=n;
- //注意下写法,l和L区别
- while(L<=R)
- {
- int mid=L+R>>1;
- if(check(mid,l,k)) ans=mid,L=mid+1;
- else R=mid-1;
- }
- printf("%d ",ans);
- }
- printf("\n");
- //初始化清空
- for(int i=1;i<=n;i++)
- for(int j=1;j<=32;j++) sum[i][j]=0;
- }
- int main()
- {
- int t=1;
- scanf("%d",&t);
- while(t--) solve();
- return 0;
- }