3689: 异或之
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 398 Solved: 184
[Submit][Status][Discuss]
Description
给定n个非负整数A[1], A[2], ……, A[n]。
对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数。求这些数(不包含A[i])中前k小的数。
注:xor对应于pascal中的“xor”,C++中的“^”。
Input
第一行2个正整数 n,k,如题所述。
以下n行,每行一个非负整数表示A[i]。
Output
共一行k个数,表示前k小的数。
Sample Input
1
1
3
4
Sample Output
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])
前5小的数:0 2 2 5 5
【数据范围】
对于100%的数据,2 <= n <= 100000; 1 <= k <= min{250000, n*(n-1)/2};
0 <= A[i] < 2^31
对二进制字典树维护一下size
就可以求异或K大值啦
中间过程用priority_queue搞搞就可以啦
再注意一下 题中 (x xor y) 和 (y xor x) 是同一种方案就好了
刚看完题 以为是线性基。。。开心打完以后才发现读错题。。。
重新YY一下 trie树+优先队列秒掉
先附赠线性基求前K小值。。。
#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;
inline int read()
{
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()
{
n=read();m=read()-1;
register int i,j,k,tmp;
for(i=1;i<=n;++i)a[i]=read();
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;
inline int read()
{
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()
{
n=read();m=read();
register int i;
for(i=1;i<=n;++i)a[i]=read();
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
*/