Loading

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

http://codeforces.com/problemset/problem/617/E

题意:给出n个数,q个询问区间,问这个区间里面有多少个区间[i,j]可以使得ai^ai+1^...^aj = k。

思路:根据xor的性质,可以处理出前缀异或和sum[],那么要使结果等于k,就是sum[i-1]^sum[j] == k,即sum[j]^k == sum[i-1],那么用一个数组cnt[]存储对于每一个sum[]的数量。然后用莫队算法做。莫队算法是一种离线处理区间问题的算法,在我看来是将询问通过分块排序成一个可以暴力处理的序列,让暴力的复杂度尽量的低。只有O(n*sqrt(n))的复杂度。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 #include <string>
 7 #include <iostream>
 8 #include <stack>
 9 #include <map>
10 #include <queue>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 #define N 100010
15 #define INF 0x3f3f3f3f
16 struct node {
17     int l, r, id;
18     LL ans;
19 } q[N*10];
20 int sum[N], kuai, k;
21 LL cnt[N*20];
22 
23 bool cmp1(const node &a, const node &b) {
24     if(a.l / kuai != b.l / kuai) return a.l / kuai < b.l / kuai; // 根据块的编号排序
25     return a.r < b.r; // 块内按照r值排序
26 }
27 
28 bool cmp2(const node &a, const node &b) {
29     return a.id < b.id;
30 }
31 
32 int main()
33 {
34     int n, m, num, L, R;
35     LL s = 0;
36     scanf("%d%d%d", &n, &m, &k);
37     for(int i = 1; i <= n; i++) {
38         scanf("%d", &num); sum[i] = sum[i-1] ^ num;
39     }
40     for(int i = 1; i <= m; i++) {
41         scanf("%d%d", &q[i].l, &q[i].r);
42         q[i].id = i; q[i].l--;
43     }
44     kuai = sqrt(n);
45     sort(q + 1, q + 1 + m, cmp1);
46     L = 1; R = 0;
47     for(int i = 1; i <= m; i++) {
48         int l = q[i].l, r = q[i].r;
49         while(L < l) {
50             cnt[sum[L]]--;
51             s -= cnt[sum[L]^k];
52             L++;
53         }
54         while(L > l) {
55             L--;
56             s += cnt[sum[L]^k];
57             cnt[sum[L]]++;
58         }
59         while(R < r) {
60             R++;
61             s += cnt[sum[R]^k];
62             cnt[sum[R]]++;
63         }
64         while(R > r) {
65             cnt[sum[R]]--;
66             s -= cnt[sum[R]^k];
67             R--;
68         }
69         q[i].ans = s;
70     }
71     sort(q + 1, q + 1 + m, cmp2);
72     for(int i = 1; i <= m; i++) printf("%lld\n", q[i].ans);
73     return 0;
74 }

 

posted @ 2017-01-12 19:49  Shadowdsp  阅读(496)  评论(0编辑  收藏  举报