https://vjudge.net/problem/CodeForces-617E
题意,给你n个数ax,m个询问Ly,Ry, 问LR内有几对i,j,使得ai^...^ aj =k.
题解:第一道莫队题。
技巧:前缀亦或。flag数组:利用XOR的性质。
莫队的区间排序及处理。
id的处理:因为排序打乱了询问顺序,所以用id记录原来的顺序。
四个月后的补充: 关于XOR的性质: x^k=y <=> x^y=k. 所以每次读入一个a[i],Ans +=flag[a[i]^k]. It would be better if we call flag a 'cnt' array!
坑点:打错了一个字母,结果tle了好久
//#define _CRT_SECURE_NO_WARNINGS #include<bits/stdc++.h> using namespace std; const int maxn = 120010; struct node { int l, r, id; }Q[maxn]; long long ans[maxn]; long long flag[5000000]; int a[maxn],pos[maxn]; int n, m, k; int L = 1, R=0; long long Ans=0; bool cmp(node a, node b) { if (pos[a.l] == pos[b.l]) return a.r < b.r; return pos[a.l] < pos[b.l]; } 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() { scanf("%d%d%d", &n, &m, &k); int sz = sqrt(n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); a[i] = a[i] ^ a[i - 1]; pos[i] = i / sz; } for (int i = 1; i <= m; i++) { scanf("%d%d", &Q[i].l, &Q[i].r); Q[i].id = i; } sort(Q + 1, Q + 1 + m,cmp); flag[0] = 1; for (int i = 1; i <= m; i++) { while (R < Q[i].r) { R++; add(R); } while (L > Q[i].l) { L--; add(L - 1); } while (R > Q[i].r) { del(R); R--; } while (L < Q[i].l) { del(L - 1); L++; } ans[Q[i].id] = Ans; // } for (int i = 1; i <= m; i++) cout << ans[i] << endl; }