5301: [Cqoi2018]异或序列
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 117 Solved: 88
[ 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
1 2 3 1
1 4
1 3
2 3
2 4
4 4
Sample Output
4
2
1
2
1
2
1
2
1
HINT
Source
这题范围是1e5。
连续异或和,一般考虑保存异或前缀和。区间静态操作题,考虑写一手莫队。
异或真是个神奇的东西。若a^b=c,则a^c=b且b^c=a。
定义cnt[i]为当前区间值为i的前缀的数量(这正是a的值域≤1e5的用意),那我们更新答案时就可以O(1)计算每个增加(删除)节点的贡献。
Code留坑。
/**************************************************************
Problem: 5301
User: LoveOI
Language: C++
Result: Accepted
Time:1568 ms
Memory:5200 kb
****************************************************************/
#include <cstdio>
#include <cmath>
#include <algorithm>
#define N 100010
using namespace std;
inline char gc() {
static char now[1<<16], *S, *T;
if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;}
return *S++;
}
inline int read() {
int x = 0; char c = gc();
while(c < '0' || c > '9') c = gc();
while(c >= '0' && c <= '9') {x = x * 10 + c - 48; c = gc();}
return x;
}
inline void print(long long x) {
if(!x) {puts("0"); return ;}
int dgt[30], now = -1;
while(x) {dgt[++now] = (int)x % 10; x/= 10;}
for(int i = now; i >= 0; --i) putchar('0' + dgt[i]); puts("");
}
int n, m, k; long long a[N], blank, s[N], answer[N], cnt[N];
struct node {int l, r, id;}q[N];
inline bool cmp1(node A, node B) {
int b1 = (A.l - 1)/blank, b2 = (B.l - 1)/blank;
if(b1 == b2) return (b1&1)?(A.r<B.r):(A.r > B.r);
return b1 < b2;
}
int main() {
n = read(); m = read(); k = read();
for(int i = 1; i <= n; ++i) a[i] = read();
s[0] = 0; for(int i = 1; i <= n; ++i) s[i] = s[i - 1] ^ a[i];
for(int i = 1; i <= m; ++i) {q[i].l = read(); q[i].r = read(); q[i].id = i;}
blank = (int)sqrt(n); sort(q+1, q+m+1, cmp1);
int l = 1, r = 0; long long ans = 0;
for(int i = 1; i <= m; ++i) {
while(l < q[i].l - 1) {--cnt[s[l]]; ans-= cnt[k^s[l]]; ++l;}
while(l > q[i].l - 1) {--l; ans+= cnt[k^s[l]]; ++cnt[s[l]];}
while(r < q[i].r) {++r; ans+= cnt[k^s[r]]; ++cnt[s[r]];}
while(r > q[i].r) {--cnt[s[r]]; ans-= cnt[k^s[r]]; --r;}
answer[q[i].id] = ans;
}
for(int i = 1; i <= m; ++i) print(answer[i]);
return 0;
}