1. 程式人生 > >BZOJ 4888 [Tjoi2017]異或和

BZOJ 4888 [Tjoi2017]異或和

fenwick oid post class ++i style names highlight 題解

題解:對每一位分別考慮貢獻

先求前綴和

按照二進制減法分類討論,求出最終這一位是1還是0

用樹狀數組維護

註意:樹狀數組對0這個位置單獨考慮

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int u=1000000;
const int maxn=100009;

int n;
int ans;
int a[maxn];

inline int lowbit(int x){
	return x&(-x);
}
inline int Ct(int x,int y){
	return x%(1<<y);
}
struct FenwickTree{
	int c[u+10];
	int cnt0;
	void Add(int x,int val){
		if(x==0){
			cnt0+=val;
		}else{
			while(x<=u){
				c[x]+=val;
				x+=lowbit(x);
			}
		}
	}
	int Querysum(int x){
		int ret=0;
		while(x){
			ret+=c[x];
			x-=lowbit(x);
		}
		return ret+cnt0;
	}
	void Cle(){
		cnt0=0;
		memset(c,0,sizeof(c));
	}
}T[2];


int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	for(int i=1;i<=n;++i)a[i]+=a[i-1];
	
	for(int j=1;j<=21;++j){
		T[0].Cle();T[1].Cle();
		T[0].Add(0,1);
		for(int i=1;i<=n;++i){
			int tmp=Ct(a[i],j-1);
			int cnt=0;
			if(a[i]&(1<<(j-1))){
				cnt+=T[0].Querysum(tmp);
				cnt+=(T[1].Querysum(u)-T[1].Querysum(tmp));
				T[1].Add(Ct(a[i],j-1),1);
			}else{
				cnt+=(T[0].Querysum(u)-T[0].Querysum(tmp));
				cnt+=T[1].Querysum(tmp);
				T[0].Add(Ct(a[i],j-1),1);
			}
			if(cnt%2!=0)ans^=(1<<(j-1));
		}
	}
	cout<<ans<<endl;
	return 0;
}

  

BZOJ 4888 [Tjoi2017]異或和