算法:
首先把前缀异或和统计出来,再将得到的每一个前缀异或和(包括pre[0]=0),塞进字典树中,接下来有一个贪心的思路:每当我拿着其中一个异或和的值时,我在字典树中尽可能找二进制高位与其对应的位不相同的异或和,这样两者异或运算后,所得值最大。
所以我们有了这样一个思路,对于每一个pre[i](1<=i<=n,忘说了pre[i]=co[1]^co[2]......^co[i]),我们找到以第i位为端点(并不一定是左端点或右端点)的区间中,异或和最大的是多少,并将n个最大值塞入一个堆中。接下来每次操作,我们将n个数中最大的取出,累计入ans,再将该最大值对应的位置,能产生的次小的异或值插入堆中(就是取出以第i位为端点的区间中,第k+1大的异或值)。
考虑怎么计算第k大,我们可以预处理出字典树每一个子树的大小,那么再利用前面那个思路的性质,可以用类似treap的算法算出第k打的异或和。最后需要注意的是,由于一个区间有两个端点,可能会重复计算一次,那么在这种情况下,我们取前2*k大的异或和,最后答案/2即可。
Code:
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define rep2(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
template<typename T> void read(T &num){
char c=getchar();num=0;T f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){num=(num<<3)+(num<<1)+(c^48);c=getchar();}
num*=f;
}
template<typename T> void qwq(T x){
if(x>9)qwq(x/10);
putchar(x%10+'0');
}
template<typename T> void write(T x){
if(x<0){x=-x;putchar('-');}
qwq(x);putchar('\n');
}
long long co[500010];long long pre[500010];
struct wzy{
int pos[2];
}tree[20000010];
int tot=1;int siz[20000010];
inline void change(long long x){
int ret=1;
rep2(i,31,0){
int tmp=(((1ll<<i)&x)!=0);siz[ret]++;
if(!tree[ret].pos[tmp])tree[ret].pos[tmp]=++tot;
ret=tree[ret].pos[tmp];
}
siz[ret]++;return;
}
priority_queue<pair<long long,pair<int,int> > >v;
inline long long query(long long x,int rk){
int ret=1;long long ans=0;
rep2(i,31,0){
int tmp=(((1ll<<i)&x)!=0);
if(!tree[ret].pos[tmp^1]){
ret=tree[ret].pos[tmp];
}else if(rk<=siz[tree[ret].pos[tmp^1]]){
ret=tree[ret].pos[tmp^1];ans|=1ll<<i;
}else{
rk-=siz[tree[ret].pos[tmp^1]];ret=tree[ret].pos[tmp];
}
}
return ans;
}
int main(){
int n,k;read(n);read(k);
rep(i,1,n){read(co[i]);pre[i]=(pre[i-1]^co[i]);}
rep(i,0,n){change(pre[i]);}
rep(i,0,n){v.push(make_pair(query(pre[i],1),make_pair(i,1)));}
long long ans=0;
rep(i,1,2*k){
long long nop=v.top().first;ans+=nop;
int nop1=v.top().second.first;int nop2=v.top().second.second;v.pop();
if(nop2<n){
v.push(make_pair(query(pre[nop1],nop2+1),make_pair(nop1,nop2+1)));
}
}
write(ans/2);
return 0;
}