[Cqoi2018]异或序列
Description
已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l、r ,问在 [l,r] 区间内,有多少连续子
序列满足异或和等于 k 。
也就是说,对于所有的 x,y (l≤x≤y≤r),能够满足a[x]^a[x+1]^…^a[y]=k的x,y有多少组。
Input
输入文件第一行,为3个整数n,m,k。
第二行为空格分开的n个整数,即ai,a2,….an。
接下来m行,每行两个整数lj,rj,表示一次查询。
1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n
Output
输出文件共m行,对应每个查询的计算结果。
Sample Input
4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4
1 2 3 1
1 4
1 3
2 3
2 4
4 4
Sample Output
4
2
1
2
1
2
1
2
1
HINT
Source
预处理前缀和。
若i-j,异或和为K。
则 sum[i-1]^sum[j]=k。
则用莫队处理,加入sum[i-1] ,每次(O1)处理,ans+=cnt[sum[i-1]^k].
#include <bits/stdc++.h> #define maxn 100005 using namespace std; struct quer { int l,r,pos; }query[maxn]; int block; bool cmp(quer a,quer b) { if(a.l/block!=b.l/block) return (a.l/block)<(b.l/block); return a.r<b.r; } int now=0,k; int ans[maxn]; int sum[maxn]; int cnt[maxn]; void add(int x) { cnt[x]++; now+=cnt[x^k]; } void dele(int x) { cnt[x]--; now-=cnt[x^k]; } int main() { int n,m,i; int a[maxn]; cin>>n>>m>>k; for(i=1;i<=n;i++) { scanf("%d",&a[i]); } block=sqrt(n); for(i=1;i<=n;i++) { sum[i]=sum[i-1]^a[i]; } for(i=1;i<=m;i++) { scanf("%d%d",&query[i].l,&query[i].r); query[i].pos=i; query[i].l--; } sort(query+1,query+1+m,cmp); int l=1,r=0; for(i=1;i<=m;i++) { while(l<query[i].l) { dele(sum[l]); l++; } while(l>query[i].l) { l--; add(sum[l]); } while(r<query[i].r) { r++; add(sum[r]); } while(r>query[i].r) { dele(sum[r]); r--; } ans[query[i].pos]=now; } for(i=1;i<=m;i++) { printf("%d\n",ans[i]); } return 0; }