题意:
n个数m次查询,每次查询给出l,r求子区间异或和为k的个数。
题解:
预处理前缀异或和,因为是区间相减求满足的所以左区间要减1。要注意数组要开2e6因为两个1e6的数异或可能会更大,答案也要开long long。
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5+10; const int maxm = 2e6+10; typedef long long ll; int n, m, k; int blk; int l, r; ll now; ll ans[maxn]; int sum[maxm], cnt[maxm]; struct ask { int x, y, qx, id; friend bool operator < (ask a, ask b) { return a.qx==b.qx?a.y<b.y:a.x<b.x; } }q[maxn]; void update(int x, int t) { if(t > 0) { now += cnt[sum[x]^k]; cnt[sum[x]]++; } else { cnt[sum[x]]--; now -= cnt[sum[x]^k]; } } int main() { scanf("%d%d%d", &n, &m, &k); for(int i = 1; i <= n; i++) scanf("%d", &sum[i]), sum[i] ^= sum[i-1]; blk = sqrt(n); for(int i = 1; i <= m; i++) { scanf("%d%d", &q[i].x, &q[i].y); q[i].qx = (q[i].x-1)/blk+1; q[i].id = i; } sort(q+1, q+m+1); l = 1; r = 0; for(int i = 1; i <= m; i++) { while(l < q[i].x-1) update(l++, -1); while(l > q[i].x-1) update(--l, 1); while(r < q[i].y) update(++r, 1); while(r > q[i].y) update(r--, -1); ans[q[i].id] = now; } for(int i = 1; i <= m; i++) printf("%lld ", ans[i]); return 0; }