给定 \(n\) 个整数 \(a_1,a_2...a_n\) ,求出所有子段异或和前 \(k\) 大的和 .
\(1\leq n\leq 5\cdot 10^5,0\leq k\leq \min(\frac{n(n-1)}{2},2\cdot 10^5),0\leq a_i\leq 2^{32}-1\)
前缀和数组为 \(b_0,b_1,b_2,\cdots b_n\) ,那么 \([l,r]\) 的字段异或和就是 \(b_r\oplus b_{l-1}\) . 就相当于两两的异或和 . 很像 \(\rm{cf241b\ friends}\) ,但是,那题 \(k\) 会达到 \(\frac{n(n-1)}{2}\) ,但是此题只会有 \(2\cdot 10^5\) ,但是 \(n\) 的大小却是 \(10\) 倍 .
所以考虑枚举出来前 \(k\) 个最大的,而不是二分,考虑用一个 \(\rm{set}\) 维护对于每个 \(i\) 没有被枚举到的最大的异或和 . 然后每次找到最大的,加入答案,然后用 \(\rm{01trie}\) 找到当前 \(i\) 下一个插入 .
但是这样就会导致一个问题,\((i,j)\) 和 \((j,i)\) 会被计算两次 . 冷静一下发现,只要把 \(k\) 的数量乘上 \(2\) 倍,这个问题就可以解决 ,前 \(k\) 大的以 \((i,j)\) 和 \((j,i)\) 的形式每个都被计算到了两次 .
需要注意的是要开 \(\rm{long\ long}\) .
时间复杂度 : \(O(k\log a)\)
空间复杂度 : \(O(n\log a)\)
code
#include<bits/stdc++.h>
using namespace std;
char in[100005];
int iiter=0,llen=0;
inline char get(){
if(iiter==llen)llen=fread(in,1,100000,stdin),iiter=0;
if(llen==0)return EOF;
return in[iiter++];
}
inline long long rd(){
char ch=get();while(ch<'0'||ch>'9')ch=get();
long long res=0;while(ch>='0'&&ch<='9')res=(res<<3)+(res<<1)+ch-'0',ch=get();
return res;
}
inline void pr(long long res){
if(res==0){putchar('0');return;}
static int out[20];int len=0;
while(res)out[len++]=res%10,res/=10;
for(int i=len-1;i>=0;i--)putchar(out[i]+'0');
}
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
const int N=5e5+10;
int cnt=1;
class node{public:int num,ch[2];}ts[N*32];
inline void init(){for(int i=0;i<N*32;i++)ts[i]=(node){0,-1};}
inline void ins(long long val){
int x=1;
for(int i=31;i>=0;i--){
int id=val>>i&1;
if(!ts[x].ch[id])ts[x].ch[id]=++cnt;
x=ts[x].ch[id];
}
ts[x].num++;
}
inline void dfs(int x){
if(ts[x].ch[0]){
dfs(ts[x].ch[0]);
ts[x].num+=ts[ts[x].ch[0]].num;
}
if(ts[x].ch[1]){
dfs(ts[x].ch[1]);
ts[x].num+=ts[ts[x].ch[1]].num;
}
}
inline long long qry(long long val,int k){
long long res=0;
int x=1;
for(int i=31;i>=0;i--){
int id=val>>i&1;
if(!id){
if(ts[x].ch[1]&&ts[ts[x].ch[1]].num>=k)x=ts[x].ch[1],res|=1ll<<i;
else k-=ts[ts[x].ch[1]].num,x=ts[x].ch[0];
}else{
if(ts[x].ch[0]&&ts[ts[x].ch[0]].num>=k)x=ts[x].ch[0],res|=1ll<<i;
else k-=ts[ts[x].ch[0]].num,x=ts[x].ch[1];
}
}
return res;
}
int n,k;
int a[N],pos[N];
set<pair<long long,int> >s;
long long ans=0;
int main(){
n=rd();k=rd();k=k<<1;n++;
for(int i=1;i<n;i++)a[i]=rd();
for(int i=1;i<n;i++)a[i]^=a[i-1];
for(int i=0;i<n;i++)ins(a[i]);
dfs(1);
for(int i=0;i<n;i++)s.insert(mp(-qry(a[i],++pos[i]),i));
for(int i=0;i<k;i++){
auto it=s.begin();
int id=it->se;
ans+=-it->fi;
s.erase(s.begin());
if(pos[id]+1<n)s.insert(mp(-qry(a[id],++pos[id]),id));
}
pr(ans/2);
return 0;
}