[Codeforces#340 div2 E. XOR and Favorite Number]莫队算法
题目链接:[Codeforces#340 div2 E. XOR and Favorite Number]
题意描述:给定
N
个数
解题思路:
- 首先预处理出前缀异或和 pre[] ,根据异或的性质,可得 ai⨁ai+1⨁…⨁aj=K⇔pre[i−1]⨁pre[j]=K 。
- 知道区间 [L,R] 的答案的情况下,如果能够在 O(1) 的时间内求出区间 [L−1,R] , [L+1,R] , [L,R−1] , [L,R+1] ,那么就可以用莫队搞了。 cnt[i] 数组用来记录区间中异或和为 i 的连续区间个数。
注意结果会爆
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define fst first
#define snd second
#define __mid__ int mid = ((l + r) >> 1)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
typedef pair<int, int> PII;
const int MAXN = 100000 + 5;
const int MX = 3e6 + 5;
const int INF = 0x3f3f3f3f;
int N, M, K, A[MAXN];
int block, pos[MAXN], pre[MAXN], lp, rp, id;
LL ans[MAXN], cnt[MX], res;
struct Q {
int l, r, id;
bool operator < (const Q& e) const {
if(pos[l] == pos[e.l]) return pos[r] < pos[e.r];
return pos[l] < pos[e.l];
}
} q[MAXN];
void add(int x) {
res += cnt[pre[x] ^ K];
cnt[pre[x]] ++;
}
void del(int x) {
cnt[pre[x]] --;
res -= cnt[pre[x] ^ K];
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while(~scanf("%d %d %d", &N, &M, &K)) {
pre[0] = 0;
block = ceil(sqrt(1.0 * N));
for(int i = 1; i <= N; i++) {
scanf("%d", &A[i]);
pre[i] = pre[i - 1] ^ A[i];
pos[i] = (i - 1) / block;
}
for(int i = 1; i <= M; i++) {
scanf("%d %d", &q[i].l, &q[i].r);
q[i].id = i;
}
sort(q + 1, q + M + 1);
memset(cnt, 0, sizeof(cnt));
cnt[0] = 1;
lp = 1, rp = 0, res = 0;
for(int i = 1; i <= M; i++) {
id = q[i].id;
while(lp > q[i].l) {
lp --;
add(lp - 1);
}
while(rp > q[i].r) {
del(rp);
rp --;
}
while(lp < q[i].l) {
del(lp - 1);
lp ++;
}
while(rp < q[i].r) {
rp ++;
add(rp);
}
ans[id] = res;
}
for(int i = 1; i <= M; i++) {
printf("%I64d\n", ans[i]);
}
}
return 0;
}