BZOJ 5301: [Cqoi2018]异或序列 莫队+桶
开一个桶记录一下前缀异或值的个数即可.
注意要把询问从 $(l,r)$ 变成 $(l-1,r)$,这样做的话会方便很多.
code:
#include <cstdio> #include <cmath> #include <algorithm> #define N 1000005 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll ans=0ll; int n,m,k,B,K; int a[N],h[N],cnt[N]; ll answer[N]; struct node { int l,r,id; node(int l=0,int r=0,int id=0):l(l),r(r),id(id){} }q[N]; bool cmp(node x,node y) { return x.l/B==y.l/B?x.r<y.r:x.l<y.l; } void del(int x) { ans-=cnt[K^x]; --cnt[x]; } void add(int x) { ++cnt[x]; ans+=cnt[K^x]; } int main() { // setIO("input"); int i,j,l=2,r=1; scanf("%d%d%d",&n,&m,&K),B=sqrt(n); for(i=1;i<=n;++i) scanf("%d",&a[i]),h[i]=h[i-1]^a[i]; for(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(i=1;i<=m;++i) { while(l>q[i].l) add(h[--l]); while(r<q[i].r) add(h[++r]); while(l<q[i].l) del(h[l++]); while(r>q[i].r) del(h[r--]); answer[q[i].id]=ans; } for(i=1;i<=m;++i) printf("%lld\n",answer[i]); return 0; }