题意:
给一个不可变序列,每次询问一个区间,问这个区间里有多少个不同的数异或后,可以使得 xor k == 0思路:
不难可以想到用莫队,但是用莫队来维护什么东西呢
我们可以想到,如果一个区间的异或值是a,a ^ k = b,那么如果存在b的情况数,那么答案可以加上b的情况数。
而当b = 0的时候,一定有一种情况数。
我们可以先作一个前缀和把a的前缀异或求出来这里要特别注意,维护莫队左右指针的时候。
当我们移动左指针的时候,由于异或的情况数是由b得到的,我们要去掉a的时候,应该要去掉a位置的前面一个,因为组合出来的a的靠a当前位置异或上前面的前缀和。
所以我们应该要去掉a前面一个位置的前缀和的计数器。
#include <bits/stdc++.h>
#define MAXN 2000005
#define ll long long
using namespace std;
struct Question {
int l, r, idx;
} qsn[MAXN];
ll ans, k;
int pos[MAXN];
int flag[MAXN];
int a[MAXN];
ll lans[MAXN];
int cmp(Question a, Question b) {
if (pos[a.l] != pos[b.l]) {
return pos[a.l] < pos[b.l];
}
return a.r < b.r;
}
void add(int x) {
ans += flag[a[x] ^ k];
flag[a[x]]++;
}
void del(int x) {
flag[a[x]]--;
ans -= flag[a[x] ^ k];
}
int main() {
int n, q;
scanf("%d %d %lld", &n, &q, &k);
int s = sqrt(n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i] ^= a[i - 1];
pos[i] = i / s;
}
for (int i = 1; i <= q; i++) {
scanf("%d %d", &qsn[i].l, &qsn[i].r);
qsn[i].idx = i;
}
sort(qsn + 1, qsn + q + 1, cmp);
flag[0] = 1;
ans = 0;
int l = 1, r = 0;
for (int i = 1; i <= q; i++) {
while (qsn[i].l < l) {
add(--l - 1);
}
while (qsn[i].l > l) {
del(l++ - 1);
}
while (qsn[i].r < r) {
del(r--);
}
while (qsn[i].r > r) {
add(++r);
}
lans[qsn[i].idx] = ans;
}
for (int i = 1; i <= q; i++) {
printf("%lld\n", lans[i]);
}
}