这道题我们发现固定一个端点,那么和他不同的或值答案就是不超过log个,因为就算每个只少一个0,那也只有20位
现在的问题是如何去重,采用的方法是对于每个右端点,用mp查找与他或起来的不同值,绑定一个三元组表示或值为u的键值对为i,j,这里我们可以覆盖掉一些被包含的点,因为不可能成为答案
之后继续去重,把包含的区间去除掉,采用的方法是排序。
之后就是个二维数点的模板,可以采用主席树来维护,这里抄了一下别人的板子
#include<bits/stdc++.h> using namespace std; #define pb push_back #define lson tr[rt].l #define rson tr[rt].r #define mid ((l+r)>>1) #define x first #define y second typedef pair<int,int> pll; typedef long long ll; const int N=1e6+100; const int mod=1e9+7; struct node{int l,r,sum;}tr[N<<5]; int tot; void build(int &rt,int l,int r){ rt=++tot; if(l==r) return; build(lson,l,mid); build(rson,mid+1,r); } void add(int &rt,int l,int r,int pre,int pos,int val){ rt=++tot;tr[rt]=tr[pre];tr[rt].sum+=val; if(l==r) return; if(pos<=mid) add(lson,l,mid,tr[pre].l,pos,val); else add(rson,mid+1,r,tr[pre].r,pos,val); } int query(int rt,int l,int r,int pre,int ql,int qr){ if(ql<=l&&r<=qr) return tr[rt].sum-tr[pre].sum; int ans=0; if(ql<=mid) ans+=query(lson,l,mid,tr[pre].l,ql,qr); if(mid<qr) ans+=query(rson,mid+1,r,tr[pre].r,ql,qr); return ans; } int a[N],root[N]; map<int,int> tmp,mp; map<int,vector<pll>> po; vector<int> add1[N],sub[N]; bool cmp(pll a,pll b){ if(a.first==b.first){ return a.second>b.second; } return a.first<b.first; } int main(){ int n,m; cin>>n; int i; for(i=1;i<=n;i++){ scanf("%d",&a[i]); tmp.clear(); for(auto u:mp) tmp[a[i]&u.first]=u.second; tmp[a[i]]=i; mp=tmp; for(auto u:mp) po[u.first].push_back({u.second,i}); } for(auto u:po){ auto v=u.second; sort(v.begin(),v.end(),cmp); vector<pll> sta; int i; for(i=0;i<v.size();i++){ if(i==0) sta.push_back(v[i]); if(v[i].second<=sta.back().second){ sta.pop_back(); } sta.push_back(v[i]); } int sz=sta.size(); for(i=0;i<sz;i++){ add1[sta[i].first].push_back(sta[i].second); if(i) sub[sta[i-1].first].push_back(sta[i].second); } } build(root[0],1,n); for(i=1;i<=n;i++){ int pre=root[i-1]; for(auto u:add1[i]) add(root[i],1,n,pre,u,1),pre=root[i]; for(auto u:sub[i]) add(root[i],1,n,pre,u,-1),pre=root[i]; } int q,las=0;scanf("%d",&q); while(q--){ int l,r;scanf("%d%d",&l,&r); l=(l^las)%n+1;r=(r^las)%n+1; if(l>r) swap(l,r); printf("%d ",las=query(root[n],1,n,root[l-1],1,r)); } }