[Acwing143] 最大異或對
阿新 • • 發佈:2022-02-25
[Acwing143] 最大異或對
- Trie樹
在給定的 \(N\) 個整數 \(A_1,A_2……A_N\)中選出兩個進行 \(xor\)(異或)運算,得到的結果最大是多少?
輸入格式
第一行輸入一個整數 \(N\)。
第二行輸入 \(N\) 個整數 \(A1~AN\)。
輸出格式
輸出一個整數表示答案。
資料範圍
\(1≤N≤10^5\),
\(0≤Ai<2^{31}\)
題解
如果要找到與某個數最大異或的數,最理想的情況是2進位制開始每位數字都是相反的。於是我們可以用Trie樹將這些數的二進位制串儲存起來,定義search
操作在樹上跑,對於每個節點,假設當前要找的串停在了1
,如果節點 0
0
,異或結果就左移一位加上1,如果不存在那麼進入節點1
,異或結果只左移。
由於\(0 \leq A_i<2^{31}\),Trie深度最多隻有\(D = 30\),因此搜尋操作時間複雜度是 \(O(D)\) 的常數級別,我們要線性掃描,對每個數找出最大異或值,因此總的時間複雜度是 \(O(Dn)\)。整棵樹最多有\(Dn\) 個節點,因此空間複雜度為 \(O(Dn)\)
- 時間複雜度 \(O(Dn)\)
- 空間複雜度 \(O(Dn)\)
題解程式碼
#include<iostream> using namespace std; const int N = 100010,M = 3000300; int a[N],son[M][2],idx=0; void insert(int x){ int p = 0; for(int i = 30;i>=0;i--){ int u = x>>i & 1; if(!son[p][u])son[p][u] = ++idx; p = son[p][u]; } } // int search(int x){ int p=0,res=0; //從最高位開始列舉 for(int i=30;i>=0;i--){ int u = x>>i & 1; if(son[p][!u]){ p = son[p][!u]; res = res*2+1; } else{ p = son[p][u]; res = res*2; } } return res; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n; cin>>n; for(int i=0;i<n;i++){ cin>>a[i]; insert(a[i]); } int res = 0; for(int i = 0;i<n;i++){ res = max(res, search(a[i])); } cout<<res<<endl; return 0; }