題解:2019十二省聯考 異或糉子

題意:

求前k大連續子段異或和

1. 做前綴異或和,然後變成求最大的k對異或和的和
2. 可以對每一個i求出第t(初始爲1)大的$a_i\ xor\ a_j$,然後把結果扔到堆裏,每次取堆頂,然後把堆頂對應的i的第t+1大的$a_i\ xor\ a_j$扔進堆裏

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;

#define re register
#define ll long long
#define gc getchar()
inline ll read()
{
 	re ll x(0);re char c(gc);
    while(c>'9'||c<'0') c=gc;
    while(c>='0'&&c<='9')x=x*10+c-48,c=gc;
    return x;
}

const int N=2e7+10; 
ll n,k,a[N][2],siz[N],m,tot;
ll ans=1,x,s[N];
struct node {int id,rk;ll w;};
bool operator < (node a,node b){return a.w<b.w;} 
priority_queue<node> q;

void ins(ll x)
{
	int u=0;
	for(int i=31;i>=0;--i)
	{
		int ch=(x>>i)&1;siz[u]++;
		if(!a[u][ch]) a[u][ch]=++tot;
		u=a[u][ch];
	}
	siz[u]++; 
}
ll query(ll x,int rk)
{
	int u=0;ll an=0;
	for(int i=31;i>=0;--i)
	{
		int ch=(x>>i)&1;
		if(!a[u][ch^1]) u=a[u][ch];
		else if(rk<=siz[a[u][ch^1]])
			u=a[u][ch^1],an|=1LL<<i;
		else 
			rk-=siz[a[u][ch^1]],u=a[u][ch];
	}
	return an;
}

int main()
{
	n=read(),k=read(),k<<=1;
	for(int i=1;i<=n;++i) x=read(),s[i]=s[i-1]^x;
	for(int i=0;i<=n;++i) ins(s[i]);
	for(int i=0;i<=n;++i) q.push((node){i,1,query(s[i],1)});
	for(int i=1;i<=k;++i)
	{
		node u=q.top();
		ans+=u.w;q.pop();
		if(u.rk<n) q.push((node){u.id,u.rk+1,query(s[u.id],u.rk+1)});
	}
	cout<<(ans>>1)<<endl; 
	return 0;
}

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章