E. XOR and Favorite Number
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard 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
input
Copy
6 2 3
1 2 1 1 0 3
1 6
3 5
output
Copy
7
0
input
Copy
5 3 1
1 1 1 1 1
1 5
2 4
1 3
output
Copy
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.
题意:给你n(<=1e5)个数,m(<=1e5)次查询,再给你一个数k(<=1e6),每次查询一个区间[l,r],问此区间内有多少个子区间的异或值为k。
思路:
对于任意一个区间,我们都可以把[l,r]的异或值化成[1,r]^[1,l-1]的值。
即 任意两个前缀异或区间(l!=r)即可唯一的确定一个原区间,且异或值可以直接算出来。
(莫队上的)l范围为0~n-1,r为1~n。(0时即所选闭区间左端点为1)
对于任意一个前缀异或值a[i],我们记录num[a[i]]为a[i]出现的次数。
因为我们求的是a[l-1]^a[r]=k
两边同时异或k得 k^a[l-1]^a[r]=0
即k^a[l-1]=a[r]
也就是说 我们每次修改i,只需要考虑k^a[i]对答案的影响以及对num[a[i]]的影响即可。
当我们加入i这个点时,先num[a[i]]++,再sum+=num[k^a[i]]。
当我们删除i这个点时,先sum-=num[k^a[i]],再num[a[i]]--。
注意上面l和r的范围不同,对应的while需要稍作修改。
代码:
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<set>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn=500010;
ll n,m,k,sz;
ll a[maxn];
ll sum,tmp[maxn],qian[maxn*10];
ll id[maxn];
ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
void add(int i,ll v)
{
if(v>0)
{
sum+=qian[a[i]^k];
qian[a[i]]+=v;
}
else
{
qian[a[i]]+=v;
sum-=qian[a[i]^k];
}
}
struct ac
{
ll x,y;
}ans[maxn];
struct node
{
int l,r,id;
}q[maxn];
bool cmp(node a,node aa)
{
return id[a.l]==id[aa.l]?a.r<aa.r:a.l<aa.l;
}
int main()
{
int T,cas=1;
while(scanf("%lld%lld%lld",&n,&m,&k)!=EOF)
{
sz=sqrt(n);
memset(tmp,0,sizeof(tmp));
memset(qian,0,sizeof(qian));
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
id[i]=(i-1)/sz+1;
if(i>1) a[i]^=a[i-1];
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].l--;
q[i].id=i;
}
sort(q,q+m,cmp);
qian[0]=1;
int l=0,r=0;sum=0;
for(int i=0;i<m;i++)
{
while(l<q[i].l){add(l,-1);l++;}
while(l>q[i].l){add(l-1,1);l--;}
while(r<q[i].r){add(r+1,1);r++;}
while(r>q[i].r){add(r,-1);r--;}
ans[q[i].id].x=sum;
}
for(int i=0;i<m;i++)
{
printf("%lld\n",ans[i].x);
}
}
return 0;
}