「题解」洛谷 CF617E XOR and Favorite Number

题目

CF617E XOR and Favorite Number

思路

莫队。

异或的性质:

1.\(a \oplus a = 0\)

2.\(a \oplus 0 = a\)

3.\(a \oplus b = k \Rightarrow a \oplus k = b\)

我们处理出原序列的前缀异或数组 \(sxor\)

如果 \([l,r]\) 这个区间的异或为 \(k\) 那么 \(sxor[r] \oplus sxor[l - 1] = k\)。(因为是 \(l-1\) 所以每个询问的左端点要左移)。

根据第三条性质,如果加入或删除某一个数 \(x\) 就变成了求 \(x \oplus k\) 的数量。

注意数组开大点。

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 100001

typedef long long ll;
ll now, ans[M];
int n, m, k, sqrn, cnt[M * 20], num[M], sxor[M];
struct query {
    int x, y, id;
    friend bool operator < (query q1, query q2) {
        if (num[q1.x] == num[q2.x]) return q1.y < q2.y;
        return num[q1.x] < num[q2.x];
    }
}q[M];

void add(int x) {
    now += cnt[x ^ k];
    ++cnt[x];
}

void del(int x) {
    --cnt[x];
    now -= cnt[x ^ k];
}

int main() {
    scanf("%d %d %d", &n, &m, &k), sqrn = sqrt(n);
    for (int i = 1, x; i <= n; ++i) {
        scanf("%d", &x);
        sxor[i] = sxor[i - 1] ^ x;
        num[i] = (i - 1) / sqrn + 1;
     }
    for (int i = 1; i <= m; ++i) {
        scanf("%d %d", &q[i].x, &q[i].y);
        --q[i].x, q[i].id = i;
    }
    std::sort(q + 1, q + m + 1);
    int l = 0, r = 0; cnt[0] = 1;
    for (int i = 1; i <= m; ++i) {
        while (l > q[i].x) add(sxor[--l]);
        while (r < q[i].y) add(sxor[++r]);
        while (l < q[i].x) del(sxor[l++]);
        while (r > q[i].y) del(sxor[r--]);
        ans[q[i].id] = now;
    }
    for (int i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
    return 0;
}
posted @ 2020-08-27 07:18  yu__xuan  阅读(145)  评论(0编辑  收藏  举报