LOJ传送门
洛谷传送门
BZOJ传送门
解析:
这个。。。其实怎么开心怎么玩就好了。
可以只建一个01Trie,然后查询前 k ∗ 2 k*2 k∗2的值就行了。
也可以只建一个可持久化的,然后每个在自己的01Trie里面查询就行了。
还是挺休闲的。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
#define int unsigned int
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
using std::cout;
using std::cerr;
cs int N=5e5+50,B=31,M=N*(B+10);
int n,k;
int rt[N],son[M][2],siz[M],tot;
inline void insert0(){
rt[0]=++tot;
siz[tot]=1;
int now=tot;
for(int re i=B;~i;--i){
son[now][0]=++tot;
now=tot;
siz[now]=1;
}
}
inline void insert(int id,int val){
int pre=rt[id-1];
int now=rt[id]=++tot;
siz[now]=siz[pre]+1;
for(int re i=B;~i;--i){
bool f=(val>>i)&1;
son[now][!f]=son[pre][!f];
son[now][f]=++tot;
siz[tot]=siz[son[pre][f]]+1;
now=son[now][f];
pre=son[pre][f];
}
}
inline int query(int id,int val,int k){
int res=0;
int now=rt[id];
for(int re i=B;~i;--i){
bool f=(val>>i)&1;
if(siz[son[now][!f]]>=k)res|=1ll<<i,now=son[now][!f];
else {
k-=siz[son[now][!f]];
now=son[now][f];
}
}
return res;
}
typedef std::pair<int,int> pii;
#define mp std::make_pair
std::priority_queue<pii,std::vector<pii> > q;
int a[N];
int rk[N];
ll ans;
signed main(){
n=getint(),k=getint();
insert0();
for(int re i=1;i<=n;++i)insert(i,a[i]=getint()^a[i-1]);
for(int re i=1;i<=n;++i)q.push(mp(query(i,a[i],rk[i]=1),i));
while(k--){
pii tmp=q.top();q.pop();
ans+=tmp.first;
q.push(mp(query(tmp.second,a[tmp.second],++rk[tmp.second]),tmp.second));
}
cout<<ans<<"\n";
return 0;
}