bzoj5301[CQOI2018]:异或序列(异或前缀和 + 莫队)

版权声明:博主是菜鸡,但转的时候还是说一声吧 https://blog.csdn.net/qq_37666409/article/details/81304705

5301: [Cqoi2018]异或序列

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 278  Solved: 209
[Submit][Status][Discuss]

Description

已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l、r ,问在 [l,r] 区间内,有多少连续子

序列满足异或和等于 k 。

也就是说,对于所有的 x,y (l≤x≤y≤r),能够满足a[x]^a[x+1]^…^a[y]=k的x,y有多少组。

Input

输入文件第一行,为3个整数n,m,k。

第二行为空格分开的n个整数,即ai,a2,….an。

接下来m行,每行两个整数lj,rj,表示一次查询。

1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n

Output

输出文件共m行,对应每个查询的计算结果。

Sample Input

4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4

Sample Output

4
2
1
2
1

HINT

CQOI胆子是真的大……CF原题都敢考……这题做D2T3不会太扯了吗

1e5静态查询,不强制在线,目测传统数据结构不好做

那就莫队吧

在此之前需要一些有关XOR的小知识:

a XOR b = c

c XOR b = a

c XOR a = b

然后就是教科书般的亵渎莫队

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 100100;
const int SIZE = 400;
const int INF = 0x3f3f3f3f;

template <typename T> inline void read(T &x) {
    int ch = getchar();
    bool f = false;
    for (x = 0; !isdigit(ch); ch = getchar()) {
        if (ch == '-') {
            f = true;
        }
    }
    for (; isdigit(ch); ch = getchar()) {
        x = x * 10 + ch - '0';
    }
    if (f) {
        x = -x;
    }
}

int cnt[MAXN], n, Q, sz, tot, K;
int XOR[MAXN], ans[MAXN];

struct Query {
    int l, r, pos;
    Query(int _l = 0, int _r = 0, int _p = 0) : l(_l), r(_r), pos(_p){}
    bool operator < (const Query &Ques) const {
        if(Ques.l / sz != l / sz) return l / sz < Ques.l / sz;
        return r< Ques.r;
    }
}q[MAXN];

void modify(int x, int k) {
    tot += (cnt[x ^ K] * k), cnt[x] += k;
}

signed main() {
    read(n), read(Q), read(K);
    sz = (int) sqrt(n);
    for(int i = 1; i <= n; i++) read(XOR[i]), XOR[i] ^= XOR[i - 1];
    for(int i = 1, x, y; i <= Q; i++) {
        read(x), read(y);
        q[i] = Query(x - 1, y, i);
    }
    sort(q + 1, q + Q + 1);
    int l = 1, r = 0;
    for(int i = 1; i <= Q; i++) {
        while(l < q[i].l) modify(XOR[l++], -1);
        while(l > q[i].l) modify(XOR[--l], 1);
        while(r < q[i].r) modify(XOR[++r], 1);
        while(r > q[i].r) modify(XOR[r--], -1);
        ans[q[i].pos] = tot;
    }
    for(int i = 1; i <= Q; i++) printf("%d\n", ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37666409/article/details/81304705