题意就不说了
这样的题乍一看感觉区间& 会有n^2级别个不同的数 其实仔细分析是没有那么多的
我们考虑维护一个map 这个map记录了当前位置以前的数&起来后可以得到的值以及他们的位置 (是连续的 可以理解为后缀&) 那么我们加入当前位置的数 并且与map中的值进行&操作(这一步我们最多得到logn个值)
然后就是一个主席树的套路了 对于在前面出现过的值 我们把它的位置-1 并且在当前位置+1 然后更新这个值的位置为当前位置 这个题可以算是区间不同数个数的一个升级版把
复杂度上限是 nlogn^2
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
int sum[N*400],ls[N*400],rs[N*400],tot,rt[N];
map<int,int>las,mp,temp;
void update(int &o,int l,int r,int pos,int val){
++tot;sum[tot]=sum[o]+val;
ls[tot]=ls[o];rs[tot]=rs[o];
o=tot;
if(l==r) return;
int mid = l+r>>1;
if(pos<=mid) update(ls[o],l,mid,pos,val);
else update(rs[o],mid+1,r,pos,val);
}
int query(int o,int l,int r,int L,int R){
if(L<=l&&R>=r) return sum[o];
int mid = l+r>>1,ans = 0;
if(L<=mid) ans+=query(ls[o],l,mid,L,R);
if(R>mid) ans+=query(rs[o],mid+1,r,L,R);
return ans;
}
int main(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
int x;
rt[i]=rt[i-1];
scanf("%d",&x);
mp[x]=i;
temp.clear();
for(auto it = mp.begin(); it!=mp.end(); ++it){
int fir = it->first;
int sec = it->second;
temp[x&fir]=max(temp[x&fir],sec);
}
for(auto it = temp.begin(); it!=temp.end(); ++it){
int fir = it->first;
int sec = it->second;
if(las[fir]!=sec){
if(las[fir]) update(rt[i],1,n,las[fir],-1);
las[fir]=sec;
update(rt[i],1,n,las[fir],1);
}
}
mp=temp;
}
int q;
scanf("%d",&q);
int lasans=0;
while(q--){
int l,r;
scanf("%d%d",&l,&r);
l=(l^lasans)%n+1;
r=(r^lasans)%n+1;
if(l>r) swap(l,r);
printf("%d\n",lasans=query(rt[r],1,n,l,r));
}
return 0;
}