传送门
1.处理出异或前缀和数组a[i]^=a[i-1];
2.对于区间[L,R]的异或和,即为a[R]^a[L-1]
3.如果x ^ y=k,那么x=k ^ y
对于一个区间[L,R],我们维护[L-1,R]的异或前缀和.
当加入新元素时a[x],如果在我们维护的前缀和里存在a[x]^k,那么就会对答案产生贡献.
##注意这个题左端点是L-1,这是关键!##
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 2000020
#define fore(n) for(int i=1;i<=n;i++)
ll n,m,k;
int a[MAXN];
ll ans[MAXN];
ll Cnt[MAXN];
int sq;
struct query // 把询问以结构体方式保存
{
int l, r, id;
bool operator<(const query &o) const // 重载<运算符,奇偶化排序
{
// 这里只需要知道每个元素归属哪个块,而块的大小都是sqrt(n),所以可以直接用l/sq
if (l / sq != o.l / sq)
return l < o.l;
if (l / sq & 1)
return r < o.r;
return r > o.r;
}
} Q[MAXN];
ll cur=0;
int flag=0;
inline void add(int p)
{
cur+=Cnt[k^a[p]];
Cnt[a[p]]++;
}
inline void del(int p)
{
Cnt[a[p]]--;
cur-=Cnt[k^a[p]];
}
int main()
{
//freopen("E://tt.txt","r",stdin);
ios::sync_with_stdio(false);
cin>>n>>m>>k;
fore(n){
cin>>a[i];a[i]^=a[i-1];}
fore(m)
{
cin>>Q[i].l>>Q[i].r;
Q[i].l--;
Q[i].id=i;
}
sq=sqrt(n);
sort(Q+1,Q+1+m);
int l=0;int r=0;
Cnt[a[0]]++;
fore(m)
{
while (l < Q[i].l)
del(l++);
while (l > Q[i].l)
add(--l);
while (r < Q[i].r)
add(++r);
while (r > Q[i].r)
del(r--);
ans[Q[i].id]=cur;
}
fore(m)
cout<<ans[i]<<endl;
}