[CQOI2018]异或序列
题目链接:[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;
}