看到区间异或和就想起来了前缀。
前置知识:(下面的[xx,yy]代表从xx到yy的异或和)
所以有:
所以预处理出所有的前缀异或和即可,由于需要,故
这里可不用map,直接sort一遍即可使得相同的值相邻,然后记录这种区间的个数。由于要在所有异或和相同的区间中选择两个区间,
贡献即:,遍历一遍即可。
又因为,故
最小为0,所以从遍历是从0到n的。(all表示前缀异或和,all[0]初始化为0)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5 + 10; int q[N], n; int all[N]; ll ans = 0; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++){ scanf("%d", &q[i]); all[i] = all[i - 1] ^ q[i]; } sort(all + 1, all + 1 + n); for(int i = 0; i <= n; ) { int j = i + 1; ll t = 1; while(j <= n && all[i] == all[j]) j++, t++; ans += (t - 1) * t / 2; i = j; } printf("%lld\n", ans); return 0; }