题目链接:[CQOI2018]异或序列


我们将序列前缀异或和处理一下就不难看出,直接莫队维护即可。

但是add和del函数要注意一些细节,
add:我们应该先计算贡献,再++,防止k=0
del:我们应该先–,再减去贡献,防止k=0

还需要注意,我们查询[l,r],但是前缀异或和预处理之后,就变成[l-1,r]了。


AC代码:

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