https://codeforces.com/contest/1113/problem/C
题意
给一段序列,求出满足下列条件的区间的个数。
- [L,R]长度为偶数
- a L ⊕ a L + 1 ⊕ a L + 2 ⋯ ⊕ a m i d = a m i d + 1 ⊕ a m i d + 2 ⊕ ⋯ ⊕ a R a_L ⊕ a_{L+1}⊕a_{L+2} \dots⊕a_{mid} =a_{mid+1}⊕a_{mid+2}⊕\dots⊕a_R aL⊕aL+1⊕aL+2⋯⊕amid=amid+1⊕amid+2⊕⋯⊕aR
题解
如果a⊕b=c⊕d,那么(a⊕b)⊕(c⊕d)=0,即只有相等的值异或才为0。
异或也有前缀异或,[L,R]的异或值为
p
r
e
R
⊕
p
r
e
L
−
1
pre_{R}⊕pre_{L-1}
preR⊕preL−1。
问题转化为
p
r
e
R
⊕
p
r
e
L
−
1
=
0
pre_{R}⊕pre_{L-1}=0
preR⊕preL−1=0,即
p
r
e
R
=
p
r
e
L
−
1
pre_{R}=pre_{L-1}
preR=preL−1。
所以可以在计算前缀积的时候就统计出
p
r
e
i
pre_{i}
prei出现的次数,只要两个相等的值就可以组成一个符合条件的区间,因为区间长度要是偶数,所以可以分奇偶来统计。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5+5;
const int mod = 1e9+7;
int a[maxn],pre[maxn];
map<int,int> cnt[2];
int main() {
int n;
scanf("%d", &n);
cnt[0][0] = 1;
int sum=0;
long long ans = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
sum^=a[i];
ans += cnt[i%2][sum];
cnt[i%2][sum]++;
}
cout << ans << endl;
return 0;
}