2020牛客寒假算法基础集训营4 D 子段异或

https://ac.nowcoder.com/acm/contest/3005/D
题目描述

输入一个数列a,你需要输出其中异或值为0的不同子段的数量。一个子段[l,r](1\leqslant l\leqslant r\leqslant n)的异或和a_{l}\oplus a_{l+1}\oplus \cdot \cdot \cdot \oplus a_{r}其中\oplus符号表示异或。两个子段被视为相同的,当且仅当其开始和结束位置均对应相同。

思路

考虑它的前缀和,如果区间[1,r]异或和为0,那么它和前面所有所有的异或和为0的连续的区间异或依然为0,如果前缀和[1,r]=a,前缀和[1,rr]=a,说明rrr中有一段为0,所以只需要从头计算前缀和,并且把每一个前缀和出现的次数记录下来,在计算当前位置的前缀和的时候,如果前面有k个和这个位置相同的前缀和,说明他可以和前面k个不同连续区间组成为0的子段。

#include <bits/stdc++.h>
#pragma warning (disable:6031)
#pragma warning (disable:4996)
#define mem(a, b) memset(a, b, sizeof a);
using namespace std;
const int N = 200100;
typedef long long ll;
int n;
int a[N];
ll f[N];
int main()
{
	scanf("%d", &n);
	ll res = 0;
	for (int i = 1; i <= n; i++) {
		scanf("%d", a + i);
	}
	ll temp = 0;
	map<ll, ll> s;
	s.clear();
	for (int i = 1; i <= n; i++) {
		temp ^= a[i];
		if (temp == 0)++res;
		if (s[temp]) {
			res += s[temp];
		}
		s[temp]++;
	}
	printf("%lld\n", res);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值