您的位置:首页 > 其它

[Trie树] BZOJ3689: 异或之

2017-07-13 17:03 211 查看

题意

给定n个非负整数A[1], A[2], ……, A


对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数。求这些数(不包含A[i])中前k小的数。

n<=100000

题解

有关Trie与二进制的一些运用之前完全不会,现在补一下。

我们可以把所以数字从高位开始插到Trie里,根据每个节点维护的size, 就可以在上面找一个数与Trie中的n个数异或值第K大。

然后就可以对全局开一个堆,每次取出来更新即可。

#include<cstdio>
#include<queue>
#include<algorithm>
#define Fir first
#define Sec second
using namespace std;
const int maxn=100005;
priority_queue< pair< int,pair<int,int> > > _heap;
int n,K,a[maxn];
struct node{
int sz; node* ch[2];
node(node* son=NULL){ ch[0]=ch[1]=son; sz=0; }
} nil,*null=&nil,*root=null;
typedef node* P_node;
void Insert(P_node &p,int val,int now){
if(p==null) p=new node(null);
p->sz++;
if(now) Insert(p->ch[(val&now)?1:0],val,now>>1);
}
int Kth(P_node p,int k,int val,int now){
if(!now) return 0;
int t=p->ch[(val&now)?1:0]->sz;
if(k<=t) return Kth(p->ch[(val&now)?1:0],k,val,now>>1);
else return now+Kth(p->ch[(val&now)?0:1],k-t,val,now>>1);
}
int main(){
freopen("bzoj3689.in","r",stdin);
freopen("bzoj3689.out","w",stdout);
scanf("%d%d",&n,&K);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
Insert(root,a[i],1<<30);
}
for(int i=1;i<=n;i++) _heap.push(make_pair(-Kth(root,2,a[i],1<<30),make_pair(i,2)));
for(int i=1;i<=2*K;i++){
pair< int,pair<int,int> > x=_heap.top(); _heap.pop();
if(i&1) printf("%d ",-x.Fir);
if(x.Sec.Sec<n) _heap.push(make_pair(-Kth(root,x.Sec.Sec+1,a[x.Sec.Fir],1<<30),make_pair(x.Sec.Fir,x.Sec.Sec+1)));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: