子数组异或和(前缀和、哈希)

题意

给定一个长度为n的整数数组a1,a2,,an

请你统计一共有多少个数组a的非空连续子数组能够同时满足以下所有条件:

  • 该连续子数组的长度为偶数。
  • 该连续子数组的前一半元素的异或和等于其后一半元素的异或和。

题目链接:https://www.acwing.com/problem/content/4510/

数据范围

2n3×105
0ai<220

思路

首先分析一下性质。

如果前一半元素的异或和等于其后一半元素的异或和,那么说明这个区间所有元素异或和为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;
}
posted @   pbc的成长之路  阅读(176)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示