Codeforces 617E XOR and Favorite Number(莫队算法)

题目大概说给一个序列,多次询问区间异或和为k的连续子序列有多少个。

莫队算法,利用异或的性质,通过前缀和求区间和,先处理出序列各个前缀和,然后每次区间转移时维护i以及i-1前缀和为某数的个数并增加或减少对答案的贡献。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 #define MAXN (1<<20)
 7 
 8 int block;
 9 struct Query{
10     int l,r,i;
11     bool operator<(const Query &q) const {
12         if(l/block==q.l/block) return r<q.r;
13         return l/block<q.l/block;
14     }
15 }query[111111];
16 
17 int n,m,k,a[111111],sum[111111];
18 
19 int cnt1[MAXN],cnt2[MAXN];
20 long long ans;
21 void left_insert(int i){
22     ++cnt1[sum[i-1]];
23     ++cnt2[sum[i]];
24     ans+=cnt2[sum[i-1]^k];
25 }
26 void left_remove(int i){
27     ans-=cnt2[sum[i-1]^k];
28     --cnt1[sum[i-1]];
29     --cnt2[sum[i]];
30 }
31 void right_insert(int i){
32     ++cnt1[sum[i-1]];
33     ++cnt2[sum[i]];
34     ans+=cnt1[sum[i]^k];
35 }
36 void right_remove(int i){
37     ans-=cnt1[sum[i]^k];
38     --cnt1[sum[i-1]];
39     --cnt2[sum[i]];
40 }
41 
42 long long res[111111];
43 
44 int main(){
45     scanf("%d%d%d",&n,&m,&k);
46     for(int i=1; i<=n; ++i){
47         scanf("%d",a+i);
48         sum[i]=sum[i-1]^a[i];
49     }
50     for(int i=0; i<m; ++i){
51         scanf("%d%d",&query[i].l,&query[i].r);
52         query[i].i=i;
53     }
54 
55     block=(int)(sqrt(n)+1e-6);
56     sort(query,query+m);
57 
58     int l=1,r=1;
59     right_insert(1);
60     for(int i=0; i<m; ++i){
61         while(l<query[i].l) left_remove(l++);
62         while(l>query[i].l) left_insert(--l);
63         while(r<query[i].r) right_insert(++r);
64         while(r>query[i].r) right_remove(r--);
65         res[query[i].i]=ans;
66     }
67 
68     for(int i=0; i<m; ++i){
69         printf("%lld\n",res[i]);
70     }
71     return 0;
72 }

 

posted @ 2016-07-17 16:04  WABoss  阅读(254)  评论(0编辑  收藏  举报