Description
Solution
对于每一个位置,维护一棵。用优先队列维护个位置的异或前缀和最大值。
空间很显然开不下,可持久化即可。
code_by_uselessName
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#define GET getchar()
#define LL long long
using namespace std;
namespace FastIO{
const LL L=(1<<20);
char buf[L],*S,*T;
#ifdef ONLINE_JUDGE
inline char getchar(){
if(S==T){T=(S=buf)+fread(buf,1,L,stdin);if(S==T)return EOF;}
return *S++;
}
#endif
inline LL read(){
LL s=0,f=1;char t=GET;
while('0'>t||t>'9'){if(t=='-')f=-1;t=GET;}
while('0'<=t&&t<='9'){s=(s<<1)+(s<<3)+t-'0';t=GET;}
return s*f;
}
}
using FastIO::read;
const LL N=500005;
LL n,K,val[N],sum[N],Ans;
struct Trie{
LL ch[2],num;
}t[N*80];
LL cnt,root[N];
struct Node{
LL Max,pos;
};
bool operator <(Node a,Node b){
return a.Max<b.Max;
}
priority_queue<Node>q;
void Insert(LL x,LL &rt,LL lst,LL Del){
rt=++cnt;LL u=rt;
for(LL i=32,dir;i>=0;i--){
dir=(x>>i)&1;
t[u].ch[dir]=++cnt;
u=t[u].ch[dir];
lst=t[lst].ch[dir];
t[u]=t[lst];t[u].num+=Del;
}
}
LL Ask(LL x,LL rt){
LL u=rt,Max=0;
for(LL i=32,dir;i>=0;i--){
dir=(x>>i)&1;
if(t[t[u].ch[dir^1]].num>0){
u=t[u].ch[dir^1];
Max|=(1ll<<i);
}
else if(t[t[u].ch[dir]].num>0)u=t[u].ch[dir];
else return Max;
}
return Max;
}
int main(){
n=read();K=read();
Insert(0,root[0],0,1);
for(LL i=1,x;i<=n;i++){
val[i]=read();
sum[i]=sum[i-1]^val[i];
Insert(sum[i],root[i],root[i-1],1);
x=Ask(sum[i],root[i]);
q.push((Node){x,i});
}
Node T;
while(K--){
T=q.top();q.pop();Ans+=T.Max;
Insert(T.Max^sum[T.pos],root[T.pos],root[T.pos],-1);
T.Max=Ask(sum[T.pos],root[T.pos]);
q.push(T);
}
cout<<Ans<<'\n';
return 0;
}