被卡常到80分的异或粽子

本人自闭

常年不码题常数巨大。。。

#include<bits/stdc++.h>
#define ll long long
#define ui unsigned int
using namespace std;
const int N=500000,M=N*33+5;

inline ui read(){
	ui x=0; char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
	return x;
}

ui n,k,L,R,mid,num=1,c[67],A;
ui ch[M][2],sum[M],ans,a[N+5];
ll tot,tt;

inline void ins(ui x){
	ui now=1,u;
	sum[1]++;
	for(int i=31;i>=0;now=ch[now][u],sum[now]++,i--){
		u=(x&c[i])>0;
		if(!ch[now][u]) ch[now][u]=++num;
	}
}

/*
   x ^ a[i] >= mid
*/

inline bool check(){
	ll now=0;
	for(ui i=0,p,u;i<=n;i++){
		p=1;
		for(int j=31;p&&j>=0;j--){
			u=(a[i]&c[j])>0;
		    if(mid&c[j]) p=ch[p][u^1];
		    else now+=sum[ch[p][u^1]],p=ch[p][u];
		}
		now+=sum[p];
		if(now>=k*2) return 1;
	}
	return 0;
}

/*
    A ^ now >= ans
*/

void Get(int p,int l,ui now,ui alr){
	if((A^now)<alr) return;
	if(l<0){ tt+=sum[p],tot+=sum[p]*(ll)(A^now); return;}
	
	alr+=c[l]&ans;
	if(ch[p][0]) Get(ch[p][0],l-1,now,alr);
	if(ch[p][1]) Get(ch[p][1],l-1,now+c[l],alr);
}

inline void solve(){
	L=0,R=(1<<32ll)-1;
	while(L<=R){
		mid=L+(ll)R>>1;
		if(check()) ans=mid,L=mid+1;
		else R=mid-1;
	}
	
	for(int i=0;i<=n;i++) A=a[i],Get(1,31,0,0);
}

int main(){
//	freopen("data.in","r",stdin);
//	freopen("data.out","w",stdout);
	
//	cout<<clock()<<endl;
	
	c[0]=1; for(int i=1;i<=31;i++) c[i]=c[i-1]+c[i-1];

	n=read(),k=read(),ins(0);
	for(int i=1;i<=n;i++) a[i]=a[i-1]^read(),ins(a[i]);
	
	solve(),tot>>=1,tt>>=1;
//	cout<<ans<<endl;
	printf("%lld\n",tot-ans*(ll)(tt-k));
	
//	cout<<clock()<<endl;
	return 0;
}

  

posted @ 2019-06-25 20:21  蒟蒻JHY  阅读(186)  评论(0编辑  收藏  举报