题意:
求前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;
}