标题效果:特定n的数量,这种需求n数22 XOR的值前者k少
首先,我们建立了一个二进制的所有数字Trie木,您可以使用Trie木size域检查出一些其他的数字XOR值首先k少
然后,我们要保持一个堆。其他XOR的整数值首先2增加堆(第一小是自己异或自己。不在题目要求范围内)。当取出一个数异或值的第k小后,将第k+1小增加堆
一个异或值会被两个数分别取出一次。所以取出奇数次时输出,取2*k次就可以
时间复杂度O(nlogn)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
using namespace std;
typedef pair<int, pair<int,int> > abcd;
struct Trie{
int siz;
Trie *son[2];
Trie();
}*null=new Trie,*root=null;
Trie :: Trie()
{
siz=0;
son[0]=son[1]=null;
}
int n,a[M];
abcd heap[M];
int top;
void Push(abcd x)
{
heap[++top]=x;
int t=top;
while( t>1 && heap[t]<heap[t>>1] )
swap(heap[t],heap[t>>1]),t>>=1;
}
void Pop()
{
heap[1]=heap[top--];
int t=2;
while( t<=top )
{
if( t<top && heap[t+1]<heap[t] )
++t;
if( heap[t]<heap[t>>1] )
swap(heap[t],heap[t>>1]),t<<=1;
else
break;
}
}
void Insert(Trie*&p,int x,int pos)
{
if(p==null)
p=new Trie();
p->siz++;
if(!pos)
return ;
Insert(p->son[x&pos?
1:0],x,pos>>1); } int Get_Kth(Trie*p,int x,int pos,int k) { if(!pos) return 0; if(k<=p->son[x&pos?1:0]->siz) return Get_Kth(p->son[x&pos?1:0],x,pos>>1,k); else return Get_Kth(p->son[x&pos?0:1],x,pos>>1,k-p->son[x&pos?
1:0]->siz)+pos; } int main() { int i,k; cin>>n>>k; for(i=1;i<=n;i++) scanf("%d",&a[i]),Insert(root,a[i],1<<30); for(i=1;i<=n;i++) Push( make_pair( Get_Kth(root,a[i],1<<30,2) , make_pair(i,2) ) ); for(i=1;i<=k<<1;i++) { abcd temp=heap[1];Pop(); if(i&1) printf("%d ",temp.first); if(temp.second.second!=n) { int x=temp.second.first; int y=temp.second.second; Push( make_pair( Get_Kth(root,a[x],1<<30,y+1) , make_pair(x,y+1) ) ); } } }
版权声明:本文博主原创文章,博客,未经同意不得转载。