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

题目链接:http://codeforces.com/problemset/problem/617/E

题目:

  给你a1 a2 a3 ··· an 个数,m次询问:在[L, R] 里面又多少中 [l, r] 使得 al xor al+1 xor ··· ar 为 k。

题解:

  本题只有区间查询没有区间修改,而且数据量不大(10w),所以可以用离线的方法解决。

  使用莫队算法来解决,就需要O(1)的修改[L, R+1] 、[L, R-1]、[L+1, R]、[L-1, R]。

  详细的莫队可以百度学一下。

  这里讲一下怎么样通过O(1)来修改

  1)我们需要求前缀xor。 

  2)[L, R] -> [L, R+1]:这里添加了一个aR+1 , 就可以通过前缀xor T,所以我们需要找 T ^ k  H 的个数(因为H^T=K-> H=T^K)。

      如果H在前面出现过,比如(全部是前缀xor)1 2 1[加入]。这时xor 为1 ,我们当k为0, 那么 0^1 = 1的个数就为1。

      这里的1的数量有什么意义。如果我们要想 1 [2 1] 这一段的xor ,是不是应该  T3(1)xor T1(1) = 0 = k;

    [L, R] -> [L, R-1] : 这里是删除了一个a, num[TaR] --, 我们要求的是 k^ TaR 的个数 。

      1 2 1 1[删除], k = 0, 0^1 = 1 , 这个有2个1。这里2个的意思 1 [2 1 1] ( T4 xor T1 = 0)和 1 2 1 [1]  (T4 xor T3 = 0),因为删去了aR 所以aR 结尾的区间就要减去。

    [L, R] -> [L-1, R] : 这个是增加多一个 aL-1  。就是在[L-1, R] 这个里面找 [L-1, r(r<R)] 使得xor 为k , 所以就需要 k^((L-1)-1)。

    [L, R] -> [L+1, R] :这里是删除了 aL 。就是在 [L, r(r<R)] 找 xor 为 k 的 。T[r]^T[L-1] = k。

       num[0] = 1 。这里是应为一开始前缀异或为0 . 

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <string>
  5 #include <algorithm>
  6 #include <cmath>
  7 #include <vector>
  8 #include <queue>
  9 #include <stack>
 10 #include <set>
 11 using namespace std;
 12 typedef long long LL;
 13 #define ms(a, b) memset(a, b, sizeof(a))
 14 #define pb push_back
 15 #define mp make_pair
 16 const int INF = 0x7fffffff;
 17 const int inf = 0x3f3f3f3f;
 18 const int mod = 1e9+7;
 19 const int maxn = 100000+10;
 20 int a[maxn];
 21 LL num[3000010];
 22 LL x[maxn];
 23 LL ans[maxn];
 24 struct Point
 25 {
 26     int l, r, id;
 27 }node[maxn];
 28 int unit, n, m, k;
 29 void init() {
 30     ms(a, 0);
 31     ms(ans, 0);
 32     ms(num, 0);
 33     ms(x, 0);
 34 }
 35 bool cmp(Point x1, Point x2)
 36 {
 37     if(x1.l/unit != x2.l/unit){
 38         return x1.l/unit < x2.l/unit;
 39     }
 40     else
 41         return x1.r < x2.r;
 42 }
 43 void work()
 44 {
 45     for(int i = 1;i<=n;i++)
 46         x[i] = x[i-1]^a[i];
 47 
 48     int L, R;
 49     LL temp = 0;
 50     L = 1, R = 0;
 51     num[0]++;
 52     for(int i = 0;i<m;i++){
 53         while(R<node[i].r){
 54             R++;
 55             temp+=num[k^x[R]];
 56             num[x[R]]++;
 57         }
 58         while(R>node[i].r){
 59             num[x[R]]--;
 60             temp-=num[x[R]^k];
 61             R--;
 62         }
 63         while(L>node[i].l){
 64             L--;
 65             temp+=num[k^x[L-1]];
 66             num[x[L-1]]++;
 67         }
 68         while(L<node[i].l){
 69             num[x[L-1]]--;
 70             temp-=num[x[L-1]^k];
 71             L++;
 72         }
 73         ans[node[i].id] = temp;
 74     }
 75 }
 76 void solve() {
 77     scanf("%d%d%d", &n, &m, &k);
 78     unit = (int)sqrt(n);
 79     for(int i = 1;i<=n;i++) scanf("%d", &a[i]);
 80     for(int i = 0;i<m;i++){
 81         node[i].id = i;
 82         scanf("%d%d", &node[i].l, &node[i].r);
 83     }
 84     sort(node, node+m, cmp);
 85     work();
 86     for(int i = 0;i<m;i++){
 87         printf("%lld\n", ans[i]);
 88     }
 89 }
 90 int main() {
 91 #ifdef LOCAL
 92     freopen("input.txt", "r", stdin);
 93 //        freopen("output.txt", "w", stdout);
 94 #endif
 95 //    ios::sync_with_stdio(0);
 96 //    cin.tie(0);
 97 
 98     init();
 99     solve();
100 
101     return 0;
102 }
View Code

 

posted @ 2017-07-16 21:51  Dh_q  阅读(212)  评论(0编辑  收藏  举报