十二省联考2019 异或粽子
十二省联考2019 异或粽子
傻逼题,全场切的那种。
显然每次取出没取过的异或和最大的区间。
对于每个r,将满足[l,r]异或和最大的区间插入进堆里。
每次取出堆顶区间,如果取出过k个以r为右端点的区间了,就向堆中插入满足[l,r]异或和第k+1大的区间。
傻逼可持久化trie,就做完了。
#include<bits/stdc++.h>
#define il inline
#define vd void
il unsigned int gi(){
unsigned int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
unsigned int a[500010];
std::priority_queue<std::pair<unsigned int,int> >que;
int rt[500010],ch[17000010][2],sum[17000010],cnt;
int qk[500010];
il int copyof(int x){
++cnt;ch[cnt][0]=ch[x][0],ch[cnt][1]=ch[x][1],sum[cnt]=sum[x];
return cnt;
}
il vd insert(int&rt,unsigned int y){
rt=copyof(rt);++sum[rt];
int x=rt;
for(int i=31;~i;--i){
bool t=(y>>i)&1;
ch[x][t]=copyof(ch[x][t]);
x=ch[x][t];++sum[x];
}
}
il unsigned int query(int x,int k,unsigned int y){
unsigned int ret=0;
for(int i=31;~i;--i){
bool t=!((y>>i)&1);
if(k<=sum[ch[x][t]])x=ch[x][t],ret|=(1u<<i);
else k-=sum[ch[x][t]],x=ch[x][!t];
}
return ret;
}
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int n=gi(),K=gi();
for(int i=1;i<=n;++i)a[i]=a[i-1]^gi();
for(int i=0;i<=n;++i){
if(i)rt[i]=rt[i-1];
insert(rt[i],a[i]);
}
for(int i=1;i<=n;++i)que.push({query(rt[i],qk[i]=1,a[i]),i});
long long ans=0;
while(K--){
int r=que.top().second;
ans+=que.top().first;
que.pop();
if(qk[r]!=r)que.push({query(rt[r],++qk[r],a[r]),r});
}
printf("%lld\n",ans);
return 0;
}
博主是蒟蒻,有问题请指出,谢谢!
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。