5301: [Cqoi2018]异或序列
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 278 Solved: 209
[Submit][Status][Discuss]
Description
已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l、r ,问在 [l,r] 区间内,有多少连续子
序列满足异或和等于 k 。
也就是说,对于所有的 x,y (l≤x≤y≤r),能够满足a[x]^a[x+1]^…^a[y]=k的x,y有多少组。
Input
输入文件第一行,为3个整数n,m,k。
第二行为空格分开的n个整数,即ai,a2,….an。
接下来m行,每行两个整数lj,rj,表示一次查询。
1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n
Output
输出文件共m行,对应每个查询的计算结果。
Sample Input
4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4
Sample Output
4
2
1
2
1
HINT
CQOI胆子是真的大……CF原题都敢考……这题做D2T3不会太扯了吗
1e5静态查询,不强制在线,目测传统数据结构不好做
那就莫队吧
在此之前需要一些有关XOR的小知识:
a XOR b = c
c XOR b = a
c XOR a = b
然后就是教科书般的亵渎莫队
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100100;
const int SIZE = 400;
const int INF = 0x3f3f3f3f;
template <typename T> inline void read(T &x) {
int ch = getchar();
bool f = false;
for (x = 0; !isdigit(ch); ch = getchar()) {
if (ch == '-') {
f = true;
}
}
for (; isdigit(ch); ch = getchar()) {
x = x * 10 + ch - '0';
}
if (f) {
x = -x;
}
}
int cnt[MAXN], n, Q, sz, tot, K;
int XOR[MAXN], ans[MAXN];
struct Query {
int l, r, pos;
Query(int _l = 0, int _r = 0, int _p = 0) : l(_l), r(_r), pos(_p){}
bool operator < (const Query &Ques) const {
if(Ques.l / sz != l / sz) return l / sz < Ques.l / sz;
return r< Ques.r;
}
}q[MAXN];
void modify(int x, int k) {
tot += (cnt[x ^ K] * k), cnt[x] += k;
}
signed main() {
read(n), read(Q), read(K);
sz = (int) sqrt(n);
for(int i = 1; i <= n; i++) read(XOR[i]), XOR[i] ^= XOR[i - 1];
for(int i = 1, x, y; i <= Q; i++) {
read(x), read(y);
q[i] = Query(x - 1, y, i);
}
sort(q + 1, q + Q + 1);
int l = 1, r = 0;
for(int i = 1; i <= Q; i++) {
while(l < q[i].l) modify(XOR[l++], -1);
while(l > q[i].l) modify(XOR[--l], 1);
while(r < q[i].r) modify(XOR[++r], 1);
while(r > q[i].r) modify(XOR[r--], -1);
ans[q[i].pos] = tot;
}
for(int i = 1; i <= Q; i++) printf("%d\n", ans[i]);
return 0;
}