题意
给定一个长度为\(n\)的整数数组\(a_1, a_2, \dots, a_n\)。
请你统计一共有多少个数组\(a\)的非空连续子数组能够同时满足以下所有条件:
- 该连续子数组的长度为偶数。
- 该连续子数组的前一半元素的异或和等于其后一半元素的异或和。
题目链接:https://www.acwing.com/problem/content/4510/
数据范围
\(2 \leq n \leq 3 \times 10^5\)
\(0 \leq a_i < 2^{20}\)
思路
首先分析一下性质。
如果前一半元素的异或和等于其后一半元素的异或和,那么说明这个区间所有元素异或和为\(0\)。并且如果某个区间所有元素的异或和为\(0\),无论怎么划分,左边元素的异或和一定等于右边元素的异或和。
区间异或和可以通过异或版的前缀和解决。如果两个点的前缀和相同,那么区间异或为\(0\)。
如果没有长度为偶数的限制,我们可以直接维护一个哈希表。现在加上偶数的限制,那么我们可以同时维护一个长度为奇数的哈希表,和一个长度为偶数的哈希表。因为两端点的下标都是奇数或者都是偶数时,区间长度才为偶数,因此对两个哈希表分别计算即可。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N = 300010, M = 2000010;
int n, a[N], cnt[M][2];
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
a[i] ^= a[i - 1];
}
ll ans = 0;
for(int i = 1; i <= n; i ++) {
if(!a[i] && i % 2 == 0) ans ++;
ans += (ll)cnt[a[i]][i % 2];
cnt[a[i]][i % 2] ++;
}
printf("%lld\n", ans);
return 0;
}
标签:前缀,元素,哈希,偶数,异或,数组,include
From: https://www.cnblogs.com/miraclepbc/p/16591022.html