BZOJ 3689 異或之 Trie樹 堆

2021-08-07 02:52:34 字數 1636 閱讀 8944

題目鏈結

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

4 5sample output

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])

前5小的數:0 2 2 5 5

【資料範圍】

對於100%的資料,2 <= n <= 100000; 1 <= k <= min;

0 <= a[i] < 2^31

trie樹+堆

可以對每乙個數的二進位制建一棵trie樹,這樣就可以通過每乙個節點的si

ze快速查詢出乙個數與其它數異或值的第

k 小

維護乙個小根堆,將每個數異或的第二小扔入堆中(第一小是它自己),表示是與這個數異或出的第二小的數,在取出堆頂的同時,則取出的數數可以看做與id

異或起來第nu

m 小的數被扔入堆中的,然後再將id

與其他數異或出的第(n

um+1

) 小的數再扔入堆中

然而這樣會有重複的答案,

a ^b和

b ^

a都會被記作答案,可以找出2∗

k 個數,肯定有一半是重複的,所以可以隔兩個一輸出即可

**如下:

#include

#include

#include

#define n 4000010

using

namespace

std;

const

int maxx=32;

int ch[n][2],size[n];

int a[n];

int top,n,m,k,ans,x;

struct elem

elem(){}

elem(int _,int __,int ___):w(_),id(__),num(___){}

};priority_queuevector

,greater> q;

void add(int t)

}int query(int id,int k)

return ans;

}int main()

return

0;}

bzoj3689 異或之 trie 堆

好多種解法,自己yy了一種二分答案 trie的做法,不過貌似還是o nlog 2n 的,看了一下popoqqq大神的題解,發現可以用堆來做,先把每個位置的最小值放入堆裡,每次彈出乙個元素,假設這個元素是對應位置的第k小,那麼把對應位置的第k 1小放入堆中。乙個巧妙的處理,因為會重複,所以取2 k次,...

bzoj 3689 異或之 字典樹 堆

給定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小的數。2 n 100000 1 k min 0 a i 2 31 先對所有數建一棵字典樹,對字典樹的每個節點記錄這個節點...

bzoj3689 異或之 字典樹 堆

給定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 0 ...