# 题目大意

$n,k<=5*10^5$

# solution

$S_i$ 为[1...i]区间的异或和,则任意一个区间[l,r]异或和为 $S_{l-1}$ xor $S_r$

# code

#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define get getchar()
#define in inline
#define int unsigned
{
int t=0; char ch=get;
while(ch<'0' || ch>'9') ch=get;
while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
return t;
}
const int _=1e6+23;
struct Trie{
int siz,ch[2];
}tr[_<<6];
int rt[_<<2], tot, s[_], n, m,now[_];
#define ls(k) tr[k].ch[c]
#define rs(k) tr[k].ch[1^c]
in void insert(int a,short x,int k1,int k2)
{
if(x<0) { tr[k2].siz=tr[k1].siz+1; return;}
int c=a>>x&1;
if(k1) rs(k2)=rs(k1);
ls(k2)=++tot;
insert(a,x-1,ls(k1),ls(k2));
tr[k2].siz=tr[ls(k2)].siz+tr[rs(k2)].siz;
}
in int query(int a,short x,int k,int lim)
{
if(x<0){ return 0;}
int c=a>>x&1;
if(tr[rs(k)].siz>=lim) return query(a,x-1,rs(k),lim)|(1<<x);
else return query(a,x-1,ls(k),lim-tr[rs(k)].siz);
}
#define mp make_pair
signed main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
rt[0]=++tot;
insert(0,31,0,rt[0]);
for(re int i=1;i<=n;++i)
{
rt[i]=++tot;
insert(s[i],31,rt[i-1],rt[i]);
}
ll ans=0; priority_queue<pair<int,int> >q; //第一维是贡献,第二维是区间右端点
for(re int i=1;i<=n;++i) {q.push(mp(query(s[i],31,rt[i],1),i)); now[i]=1;}
while(m--)
{
ans+=q.top().first; int u=q.top().second; q.pop();
q.push(mp(query(s[u],31,rt[u],++now[u]),u));
}
cout<<ans<<endl;
return 0;
}


posted @ 2021-04-03 22:34  yzhx  阅读(30)  评论(0编辑  收藏  举报