莫队板题,唯一难点是知道如何处理区间异或
题目中说是区间,则可以转化为前缀和的形式。
令Si=a1 xor a2 xor .... xor ai;
则 al xor a(l+1) xor a(l+2) ... xor ar = Sr xor S(l-1)
然后每次询问就可转化为在 [ l-1,r ] 之间有多少个Si 和 Sj (i<=j) 使得Si xor Sj = k;
又因为Si xor Sj = k 即 Si xor k = Sj
#include<bits/stdc++.h>
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define fi first
#define se second
#define endl '\n'
#define bug printf("bug");
using namespace std;
const int N=2e5+10,S=2e6+10;
const int INF=0x3f3f3f3f;
const long long LNF=0x3f3f3f3f3f3f3f3f;
int n,m,k,len;
long long s[N],cnt[S];
long long ans=0;
long long res[S];
struct node{
int l,r,id,from;
};
node query[S];
int get(int x){
return x/len;
}
int cmp(const node&w,const node&q){
if(w.from!=q.from) return w.from<q.from;
if(w.from&1) return w.r<q.r;
return w.r>q.r;
}
void solve(){
scanf("%d %d %d",&n,&m,&k);
len = max(1,(int)sqrt(n));
for(int i=1;i<=n;i++) scanf("%lld",&s[i]),s[i]=s[i]^s[i-1];
for(int i=1;i<=m;i++){
int l,r; scanf("%d %d",&l,&r);
query[i]={l,r,i,get(l)};
}
cnt[0]++;
sort(query+1,query+m+1,cmp);
int l=1,r=0;
for(int i=1;i<=m;i++) {
while(r<query[i].r){
r++;
ans+=cnt[s[r]^k];
cnt[s[r]]++;
}
while(l>query[i].l){
l--;
ans+=cnt[s[l-1]^k];
cnt[s[l-1]]++;
}
while(r>query[i].r){
cnt[s[r]]--;
ans-=cnt[s[r]^k];
r--;
}
while(l<query[i].l){
cnt[s[l-1]]--;
ans-=cnt[s[l-1]^k];
l++;
}
res[query[i].id] = ans;
}
for(int i=1;i<=m;i++){
printf("%lld\n",res[i]);
}
}
int main(){
int t; t=1;
//scanf("%d",&t);
while(t--){
solve();
}
return 0 - 0;
}