[CF617E]XOR and Favorite Number/[CQOI2018]异或序列
题目大意:
给定一个长度为$n(n\leq10^5)$的数列$A$和数$k$$(A_i,k\leq10^6)$。$m$组询问,每次询问区间$[l,r]$中有多少对$i,j(l\leq i\leq j\leq r)$,满足$\oplus_{x=i}^jA_x=k$。
思路:
莫队。
首先求出数列$A$的前缀异或和$pre[i]$。每次加入一个数$x$时,$cnt[x]++$,$ans+=cnt[x\oplus k]$。删除同理。
注意区间的范围,因为$\oplus_{x=i}^jA_x=pre[j]\oplus pre[i-1]$,所以对于询问$[l,r]$,实际维护的区间应该是$[l-1,r]$。
1 #include<cmath> 2 #include<cstdio> 3 #include<cctype> 4 #include<algorithm> 5 typedef long long int64; 6 inline int getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register int x=ch^'0'; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 11 return x; 12 } 13 const int N=100001,M=100000,logK=20; 14 int k,a[N],bel[N],cnt[1<<logK]; 15 int64 ans[M],tmp; 16 struct Query { 17 int l,r,id; 18 bool operator < (const Query &another) const { 19 return bel[l]<bel[another.l]||(bel[l]==bel[another.l]&&bel[r]<bel[another.r]); 20 } 21 }; 22 Query q[M]; 23 inline void ins(const int &x) { 24 tmp+=cnt[a[x]^k]; 25 cnt[a[x]]++; 26 } 27 inline void del(const int &x) { 28 cnt[a[x]]--; 29 tmp-=cnt[a[x]^k]; 30 } 31 int main() { 32 const int n=getint(),m=getint(),block=sqrt(n); 33 k=getint(); 34 for(register int i=1;i<=n;i++) { 35 a[i]=a[i-1]^getint(); 36 bel[i]=i/block; 37 } 38 for(register int i=0;i<m;i++) { 39 const int l=getint()-1,r=getint(); 40 q[i]=(Query){l,r,i}; 41 } 42 std::sort(&q[0],&q[m]); 43 for(register int i=0,l=0,r=-1;i<m;i++) { 44 while(r<q[i].r) ins(++r); 45 while(l>q[i].l) ins(--l); 46 while(r>q[i].r) del(r--); 47 while(l<q[i].l) del(l++); 48 ans[q[i].id]=tmp; 49 } 50 for(register int i=0;i<m;i++) { 51 printf("%lld\n",ans[i]); 52 } 53 return 0; 54 }