# BZOJ 3689: 异或之 字典树 优先队列

## 3689: 异或之

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 398  Solved: 184
[Submit][Status][Discuss]

共一行k个数，表示前k小的数。

4 5
1
1
3
4

0 2 2 5 5

## HINT

【样例解释】
1 xor 1 = 0 (A[1] xor A[2])
1 xor 3 = 2 (A[1] xor A[3])
1 xor 4 = 5 (A[1] xor A[4])
1 xor 3 = 2 (A[2] xor A[3])
1 xor 4 = 5 (A[2] xor A[4])
3 xor 4 = 7 (A[3] xor A[4])

【数据范围】
对于100%的数据，2 <= n <= 100000； 1 <= k <= min{250000, n*(n-1)/2}；
0 <= A[i] < 2^31

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;

{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=100100;

int n,m,z,a[N];

void guass()
{
register int i,j,k=0;
for(j=30;j>=0;j--)
{
for(i=k+1;i<=n;++i)if(a[i]&(1<<j))break;
if(i>n)continue;k++;swap(a[i],a[k]);
for(i=1;i<=n;++i)if(i!=k&&(a[i]&(1<<j)))a[i]^=a[k];
}
z=n-k;n=k;
}

inline query_kth(int k)
{
register int res=0,i;
for(i=n;i>=1;i--)if(k&(1<<(i-1)))res^=a[i];
return res;
}

int main()
{
register int i,j,k,tmp;
guass();
for(i=1;i<=(n>>1);++i)swap(a[i],a[n-i+1]);
i=tmp=0;k=0;j=z;
while(i<m)
{
if(!j){tmp=query_kth(++k);print(tmp);putchar(' ');j=z;}
else {print(tmp);putchar(' ');j--;}
i++;
}
j?print(tmp):print(query_kth(++k));
puts("");return 0;
}
/*
4 5
1 1 3 4

0 2 2 5 5
*/

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;

{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=100100;

int n,m,root,cnt,a[N];

struct trie{int ls,rs,sz;}tr[N<<5];

struct node
{
int rk,key,val;
friend bool operator <(const node &x,const node &y){return x.val>y.val;}
};

void insert(int &k,int pos,int x)
{
if(!k)k=++cnt;
tr[k].sz++;if(!(~pos))return ;
x&(1<<pos)?insert(tr[k].rs,pos-1,x):insert(tr[k].ls,pos-1,x);
}

inline int query_kth(int x,int rk)
{
register int pos=30,res=0,k=root;
while(~pos)
{
if(x&(1<<pos))
{
if(tr[tr[k].rs].sz>=rk)k=tr[k].rs;
else rk-=tr[tr[k].rs].sz,k=tr[k].ls,res+=1<<pos;
}
else
{
if(tr[tr[k].ls].sz>=rk)k=tr[k].ls;
else rk-=tr[tr[k].ls].sz,k=tr[k].rs,res+=1<<pos;
}
pos--;
}
return res;
}

priority_queue<node>q;

int main()
{
register int i;
for(i=1;i<=n;++i)insert(root,30,a[i]);
node tmp;
for(i=1;i<=n;++i){tmp.key=a[i];tmp.rk=2,tmp.val=query_kth(a[i],2);q.push(tmp);}
for(i=1;i<=(m)<<1;++i)
{
tmp=q.top();q.pop();
if(i&1)print(tmp.val),putchar(' ');
if(tmp.rk<=n)
{
tmp.rk++;tmp.val=query_kth(tmp.key,tmp.rk);
q.push(tmp);
}
}
puts("");//print(q.top().val);
return 0;
}
/*
4 5
1 1 3 4

0 2 2 5 5
*/