bzoj5301[CQOI2018]:異或序列(異或前綴和 + 莫隊)

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章