E. XOR and Favorite Number

time limit per test4 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pair li and ri and asks you to count the number of pairs of integers i and j, such that l ≤ i ≤ j ≤ r and the xor of the numbers ai, ai + 1, …, aj is equal to k.

Input
The first line of the input contains integers n, m and k (1 ≤ n, m ≤ 100 000, 0 ≤ k ≤ 1 000 000) — the length of the array, the number of queries and Bob’s favorite number respectively.

The second line contains n integers ai (0 ≤ ai ≤ 1 000 000) — Bob’s array.

Then m lines follow. The i-th line contains integers li and ri (1 ≤ li ≤ ri ≤ n) — the parameters of the i-th query.

Output
Print m lines, answer the queries in the order they appear in the input.

Examples
inputCopy

6 2 3
1 2 1 1 0 3
1 6
3 5
outputCopy
7
0
inputCopy
5 3 1
1 1 1 1 1
1 5
2 4
1 3
outputCopy
9
4
4
Note
In the first sample the suitable pairs of i and j for the first query are: (1, 2), (1, 4), (1, 5), (2, 3), (3, 6), (5, 6), (6, 6). Not a single of these pairs is suitable for the second query.

In the second sample xor equals 1 for all subarrays of an odd length.


题目大意:m次询问,求一个区间里面的子区间异或等于k的区间的个数。


不难发现是一道莫队,因为询问的是子区间,所以我们可以用前缀和先预处理输入的数组。

对于某一个加进来的数字,我们增加的值就是,k ^ a[x] 的个数,然后减少的值也是 ,k ^ a[x] 的个数,但是要注意,增加时先记录答案,再让 a[x] 的个数加一,减少时先让 a[x] 的个数减一,再记录答案。因为如果增加一个数字,那么增加的数字不能被更新,因为我们是记录的异或前缀和,[l,r] = [1,l-1] ^ [1,r],这个增加的数字不能作为左区间。

还要注意,因为我们记录的前缀和,所以查询的区间变成 [ l - 1 , r ] 即可。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,m,bl,a[N],cnt[N*20],k,res[N],s,cl=1,cr;
struct node{
	int l,r,id;
}t[N];
int cmp(const node &s1,const node &s2){
	return (s1.l/bl==s2.l/bl)?(s1.r<s2.r):(s1.l<s2.l);
}
inline void add(int x){
	s+=cnt[k^a[x]];	cnt[a[x]]++;
}
inline void del(int x){
	cnt[a[x]]--;	s-=cnt[k^a[x]];
}
signed main(){
	scanf("%lld %lld %lld",&n,&m,&k);	bl=sqrt(n);
	for(int i=1;i<=n;i++)	scanf("%lld",&a[i]);
	for(int i=1;i<=n;i++)	a[i]^=a[i-1];
	for(int i=1;i<=m;i++)	scanf("%lld %lld",&t[i].l,&t[i].r),t[i].id=i,t[i].l--;
	sort(t+1,t+1+m,cmp);
	for(int i=1;i<=m;i++){
		int L=t[i].l;	int R=t[i].r;
		while(cr<R)	add(++cr);
		while(cl>L)	add(--cl);
		while(cr>R)	del(cr--);
		while(cl<L)	del(cl++);
		res[t[i].id]=s;
	}
	for(int i=1;i<=m;i++)	printf("%lld\n",res[i]);
	return 0;
}