BZOJ3689: 异或之

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++中的“^”。

 


【数据范围】

 对于100%的数据,2 <= n <= 100000; 1 <= k <= min{250000, n*(n-1)/2};

        0 <= A[i] < 2^31

 

 

Solution

两两异或,经典的0/1trie问题。

通过记录子树的size可以二分找到第k大。

然后比较暴力地找前k大。

把trie建好。

首先把所有的数与其他数异或值的第二大放进堆里。(第一大一定是自己,不符合题意)

这样,最小的肯定包含了。把最小的取出来。然后把产生这个最小值的数的第三大异或值再放进去。。。

第二小的异或值肯定也包含了。

注意的是,每个异或值取过最小的时候,必然另一半也会把这个最小值放进去。

所以每个异或值会出现两遍。

只要取2*k次堆顶,奇数次输出答案即可。

posted @ 2018-10-26 08:09  *Miracle*  阅读(315)  评论(0编辑  收藏  举报