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次堆顶,奇数次输出答案即可。