[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 }

 

posted @ 2018-02-07 09:17  skylee03  阅读(116)  评论(0编辑  收藏  举报