P4462 [CQOI2018]异或序列
思路
把序列求前缀异或和一下
问题转变成了[l,r]中有多少个数对(x,y)的异或和为k
然后莫队就好了
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
int n,m,k,a[100100],belong[100100],sz,num,L,R,ans[100100],barrel[2001000],sum=0;
struct Query{
int l,r,id;
bool operator < (const Query &b){
return (belong[l]==belong[b.l])?r<b.r:belong[l]<belong[b.l];
}
}Q[100100];
void init(void){
sz=sqrt(n);
num=n/sz;
if(n%sz)
num++;
for(int i=1;i<=n;i++)
belong[i]=i/sz+1;
}
void moveL(int opt){
if(opt==1){
barrel[a[L]]--;
sum-=barrel[k^a[L]];
L++;
}
else{
L--;
sum+=barrel[k^a[L]];
barrel[a[L]]++;
}
}
void moveR(int opt){
if(opt==1){
R++;
sum+=barrel[k^a[R]];
barrel[a[R]]++;
}
else{
barrel[a[R]]--;
sum-=barrel[k^a[R]];
R--;
}
}
int main(){
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),a[i]^=a[i-1];
init();
for(int i=1;i<=m;i++){
scanf("%d %d",&Q[i].l,&Q[i].r);
Q[i].l--;
Q[i].id=i;
}
sort(Q+1,Q+m+1);
L=1;
R=0;
sum=0;
for(int i=1;i<=m;i++){
while(L<Q[i].l)
moveL(1);
while(L>Q[i].l)
moveL(-1);
while(R<Q[i].r)
moveR(1);
while(R>Q[i].r)
moveR(-1);
ans[Q[i].id]=sum;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}