Codeforces 1054D Changing Array

Codeforces 1054D Changing Array


做法:给定一个序列,每个数可以把在2进制k位下取反,也可以不变,在改变后,这个序列异或和不为0的区间的个数。考虑如何求出尽可能少的异或为0的序列,对序列求前缀之后,就相当与问这个前缀的序列中,有多少对的值相同,注意还有开始的0。那么对于所有数取值为min(a,~a),现在我们需要最小化,更新后同一种数中出现的相同的数对的个数,即\(C(a,2) + C(w-a,2)\),w是这种数的个数,a是取反的数的个数,当\(a = \frac{w}{2}\)时,答案最小,对于每一种都计算即可。

#include <bits/stdc++.h>
typedef long long ll;
const int N = 2e5 + 7;
using namespace std;
int n, k, lim, a[N];
map<int,int> M;
ll C(ll x) { return x*(x-1LL)>>1LL; }
int main() {
	scanf("%d%d",&n,&k);
	lim = (1ll<<k) - 1ll;
	for(int i = 1; i <= n; ++i) scanf("%d",&a[i]);
	for(int i = 2; i <= n; ++i) a[i] ^= a[i-1];
	for(int i = 0; i <= n; ++i) a[i] = min(a[i], lim-a[i]), ++M[a[i]];
	ll ans = C(n+1);
	for(map<int,int>::iterator it = M.begin(); it != M.end(); ++it) {
		int w = (*it).second;
		ans -= C( w>>1 ) + C( w - (w>>1) );
	}
	printf("%lld\n", ans);
	return 0;
}
posted @ 2018-11-04 00:39  RRRR_wys  阅读(180)  评论(0编辑  收藏  举报