题目
题目传送门
题意:给你一个大小为n的序列,然后给你一个数字k,再给出m组询问,询问给出一个区间,问这个区间里面有多少个区间的异或结果为k
题解
这是道sb题劝大家不要写
- 设 a [ i ] a[i] a[i]为 1 1 1~ i i i区间的异或前缀和,那么区间 [ L , R ] [L,R] [L,R]的异或和为 a [ L − 1 ] x o r a [ R ] a[L-1] \ xor \ a[R] a[L−1] xor a[R](异或的自反性)
- 如果 a x o r b = c a \ xor \ b = c a xor b=c,那么 a x o r c = b a \ xor \ c = b a xor c=b
- 知道了上面那个性质之后我们发现如果我们知道 a x o r k a \ xor \ k a xor k等于哪些数,我们就可以知道 a x o r a \ xor a xor哪些数等于 k k k
- 设 f [ i ] f[i] f[i]表示数字 i i i出现的次数
- 最后莫队离线维护一下即可(开数组时注意下数组大小)
code
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxm = (1 << 20);
template <typename T>
inline void read(T &s) {
s = 0;
T w = 1, ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
s *= w;
}
LL n, m, k, ans;
LL a[maxm], f[maxm], res[maxm], belong[maxm];
struct query { int l, r, id; } q[maxm];
inline bool cmp(query A, query B) {
return belong[A.l] == belong[B.l] ? A.r < B.r : A.l < B.l;
}
inline void add(int x) {
ans += f[ a[x] ^ k];
f[ a[x] ]++;
}
inline void del(int x) {
f[ a[x] ]--;
ans -= f[ a[x] ^ k ];
}
int main() {
read(n); read(m); read(k);
int blo = n / sqrt(m);
for (int i = 1; i <= n; ++i) {
read(a[i]);
a[i] ^= a[i - 1];
belong[i] = (i - 1) / blo + 1;
}
for (int i = 1; i <= m; ++i) {
read(q[i].l), read(q[i].r);
q[i].id = i;
}
sort(q + 1, q + m + 1, cmp);
f[0] = 1;
int l = 1, r = 0;
for (int i = 1; i <= m; ++i) {
int ql = q[i].l, qr = q[i].r;
while (l < ql) { del(l - 1); ++l; }
while (l > ql) { l--, add(l - 1); }
while (r < qr) add(++r);
while (r > qr) del(r--);
res[ q[i].id ] = ans;
}
for (int i = 1; i <= m; ++i)
printf("%lld\n", res[i]);
return 0;
}