【演算法競賽進階指南】字典樹 The XOR Largest Pair
阿新 • • 發佈:2020-11-03
題意
給出 N 個數字,任意選擇兩個數字進行異或運算,求結果最大值。
思路
我們對於每個數字求與其異或得到的最大值,求這 N 個最大值的最大值。
把每個數字看做一個長度為 32 的二進位制串,將其翻轉,更新到 trie 中。
對於每個二進位制串 \(S\),遍歷其值 \(S_i\)。
在 trie 中每次都嘗試向下訪問與 \(S_i\) 相反的字元。
如果能向下訪問那麼向下訪問,當前數字增加 \(1LL<<(31-i)\) ( 字元下標從 0 開始),
否則向下訪問與當前字元相同的節點。
程式碼
#include<bits/stdc++.h> typedef long long ll; using namespace std; const ll N=2e6+10; ll arr[N]; int tot=1,trie[N][2]; ll s[N]; void insert() { ll p=1; for(ll i=0;i<32;i++){ ll now=s[i]; if(!trie[p][now]){ trie[p][now]=++tot; } p=trie[p][now]; } } ll solve() { ll rel=0,p=1,cnt=31; for(ll i=0;i<32;i++,cnt--){ ll now=1^s[i]; if(trie[p][now]){ rel+=(1LL<<cnt); }else{ now=s[i]; } p=trie[p][now]; } return rel; } int main() { ll n,rel=0; scanf("%lld",&n); for(ll i=1;i<=n;i++){ scanf("%lld",&arr[i]); for(ll j=0;j<32;j++){ s[31-j]=(arr[i]&(1LL<<j))?1:0; } insert(); rel=max(rel,solve()); } printf("%lld\n",rel); return 0; }