题意

给一个长度为\(n\)的位数为\(k\)的整数数列\(a\),一次操作可将任意\(a_i\)取反,问经过任意次操作后最多有多少个区间异或和不为\(0\)

分析

求出前缀异或和,区间异或和为\(0​\)的区间数转化为求有多少对前缀异或和相等,然后用总区间数减一下,

对一个\(a_i​\)取反等同于对这个位置的前缀异或和取反,所以每个位置的前缀异或和有两种,贪心取当前值出现次数最小的一种,

总区间数为\(n*(n+1)/2​\) ,对于每个非\(0​\)数字减去\(C(x,2)​\),\(x​\)为这个数的出现次数,对于\(0​\)要减去\(C(x+1,2)​\),可以在数列中加一个\(0​\)消除这个影响

Code

#include<bits/stdc++.h>
#define fi first
#define se second
#define bug cout<<"--------------"<<endl
using namespace std;
typedef long long ll;
const double PI=acos(-1.0);
const double eps=1e-6;
const int inf=1e9;
const ll llf=1e18;
const int mod=1e9+7;
const int maxn=2e5+10;
int n,k;
int a[maxn];
int b[maxn];
map<int,int>f;
int col(int x){
	return ((1<<k)-1-x);
}
vector<int>q;
int main(){
	ios::sync_with_stdio(false);
	//freopen("in","r",stdin);
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[i]^=a[i-1];
	}
	for(int i=0;i<=n;i++){
		int x=col(a[i]);
		if(f[x]<f[a[i]]){
			a[i]=x;
		}
		if(!f[a[i]]) q.push_back(a[i]);
		f[a[i]]++;
	}
	ll ans=1ll*n*(n+1)/2;
	for(int x:q){
		ans-=1ll*f[x]*(f[x]-1)/2;
	}
	cout<<ans;
	return 0;
}