P5283 [十二省联考2019]异或粽子
思路
类似Argus那题的思路,每个维护当前位置和第x大的值,取出堆顶后放入下一个,就是当前位置的第x+1大的值
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define int long long
using namespace std;
const int MAXlog = 33;
struct Node{
int son[2],sz;
}Trie[500100*50];
int root[500100],Nodecnt;
void insert(int d,int val,int &o){
++Nodecnt;
Trie[Nodecnt]=Trie[o];
o=Nodecnt;
Trie[o].sz++;
if(d>=0)
insert(d-1,val,Trie[o].son[(val>>d)&1]);
}
int query(int root,int val,int d,int k){
if(d==-1)
return 0;
if(Trie[Trie[root].son[!((val>>d)&1)]].sz>=k)
return (1LL<<d)+query(Trie[root].son[!((val>>d)&1)],val,d-1,k);
else
return query(Trie[root].son[((val>>d)&1)],val,d-1,k-(Trie[Trie[root].son[!((val>>d)&1)]].sz));
}
struct QNode{
int kx,pos,val;
bool operator < (const QNode &b)const {
return val<b.val;
}
};
priority_queue<QNode> q;
int sumx[500100],x[500100],n,k;
signed main(){
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
scanf("%lld %lld",&n,&k);
insert(MAXlog,0,root[0]);
for(int i=1;i<=n;i++){
scanf("%lld",&x[i]);
sumx[i]=sumx[i-1]^x[i];
// printf("%lld ",sumx[i]);
root[i]=root[i-1];
insert(MAXlog,sumx[i],root[i]);
}
for(int i=1;i<=n;i++){
// int x;
q.push((QNode){1,i,query(root[i-1],sumx[i],MAXlog,1)});
// printf("push:%lld\n",x);
}
int ans=0;
for(int i=1LL;i<=k;i++){
QNode x=q.top();
q.pop();
ans+=x.val;
q.push((QNode){x.kx+1,x.pos,query(root[x.pos-1],sumx[x.pos],MAXlog,x.kx+1)});
}
printf("%lld\n",ans);
return 0;
}