http://codeforces.com/problemset/problem/617/E
首先,异或和满足
ai^ai+1^...^aj=(a1^...^ai-1)^(a1^...^aj)
所以维护前缀和可以O(1)算出一段区间的异或和
对于每次询问,可以考虑莫队算法暴力移动统计每个点在区间[l,r]中的贡献
复杂度O(n√n)
#include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #define FOR(i,s,t) for(register int i=s;i<=t;++i) using std::sort; using std::cout; typedef long long ll; const int N=100011; const int M=2000011; int blo; struct question{ int l,r,id; inline bool operator<(question A)const{ return l/blo<A.l/blo||(l/blo==A.l/blo&&r/blo<A.r/blo); } }q[N]; int n,m,k,l,r; ll tot; int hv[M],a[N]; ll ans[N]; inline void add(int x){tot+=1ll*hv[x^k];++hv[x];} inline void del(int x){--hv[x];tot-=1ll*hv[x^k];} int main(){ scanf("%d%d%d",&n,&m,&k); blo=sqrt(n); FOR(i,1,n){ scanf("%d",a+i); a[i]^=a[i-1]; } FOR(i,1,m){ scanf("%d%d",&q[i].l,&q[i].r); --q[i].l; q[i].id=i; } sort(q+1,q+m+1); l=1,r=0; FOR(i,1,m){ while(l<q[i].l)del(a[l++]); while(q[i].l<l)add(a[--l]); while(r<q[i].r)add(a[++r]); while(q[i].r<r)del(a[r--]); ans[q[i].id]=tot; } FOR(i,1,m)cout<<ans[i]<<' '; return 0; }