#include<bits/stdc++.h> using namespace std; const int mod=998244353; int dx[4]={0,0,-1,1}; int dy[4]={-1,1,0,0}; #define int long long typedef pair<int,int> pii; const int N=200010; int pre[N][32]; int a[N]; int check(int l,int x) { int sum=0; int res=1; for(int i=0;i<31;i++) { if(pre[x][i]-pre[l-1][i]==(x-l+1)) { sum+=res; } res<<=1; } return sum; } void solve() { int n; cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=0;i<31;i++)//外层循环为每一数的每一位 { for(int j=1;j<=n;j++) { if(a[j]>>i&1)pre[j][i]=pre[j-1][i]+1; else pre[j][i]=pre[j-1][i]; } } int cnt=0; int q; cin>>q; while(q--) { int l,k; cin>>l>>k; int ll=l-1,r=n+1; while(ll+1<r) { int mid=ll+r>>1; // cout<<mid<<"++"<<endl; if(check(l,mid)>=k)ll=mid; else r=mid; } int t=check(l,ll); //cout<<ll<<"++"<<endl; if(ll!=l-1)cout<<ll<<" "; else cout<<"-1 "; //cout<<endl; } cout<<endl; } signed main() { int good_luck_to_you; ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); // cout<<s.count({100,100})<<"__"<<endl; cin>>good_luck_to_you; while(good_luck_to_you--) { solve(); } system("pause"); }
思路:本题是利用位运算和前缀和的知识,因为涉及到&,所以按位运算。
我主要是卡在不知道怎么求出某一个区间的 &,在看完题解后,随着数组长度的增加,该区间的&不会增加,是非递减的。(符合二分的性质)
对于一个区间的&,我们算出每位在[l,r]为0或1,只要该位在[l,r]区间的值为r-l+1,则该位即可以取到1(这步在二分中做。
对于无解的情况,只要判断最后的mid是否等于l-1。