異或最大值
阿新 • • 發佈:2018-07-16
pre tmp 數字 markdown %d getchar using 整數 getch
1、1216: 異或最大值
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1216
Time Limit: 2 Sec Memory Limit: 128 Mb
Description
給定一些數,求這些數中兩個數的異或值最大的那個值
Input
多組數據。第一行為數字個數n,1 <= n <= 10 ^ 5。接下來n行每行一個32位有符號非負整數。
Output
任意兩數最大異或值
Sample Input
3
3
7
9Sample Output
14
Hint
Source
CSGrandeur的數據結構習題
思路:
暴力\(N^2\)
貪心一下
xor 即不同為1,相同為0
如果一個數a去找能得到 最大異或值 的b
(我也搞不清楚哪裏是最高位了,就把最右邊當第一位吧)
則二進制較高位不同的數字一定比他們二進制較高位相同的異或值大
比如 有三個數 10 6 8
10的二進制是1010
6的二進制是0101
8的二進制是1000
則和10異或值最大的就是8(第4位比較)
貪心好了
下面就該實現了
二進制無非就0和1
要快速查找,就可以建一個01字典樹
比如這樣
當範圍大到int也最多有30層 時間復雜度\(nlogn\)
考試居然忘了輸出\n了,我TM真的是,╮(╯▽╰)╭ 哎
/* ▍ ★∴ ....▍▍....█▍ ☆ ★∵ ..../ ◥█▅▅██▅▅██▅▅▅▅▅███◤ .◥███████████████◤ ~~~~◥█████████████◤~~~~ */ #include <iostream> #include <cstring> #include <cstdio> using namespace std; inline int read() { int x=0,f=1;char s=getchar(); while('0'>s||s>'9') {if(s=='-')f=-1;s=getchar();} while('0'<=s&&s<='9') {x=x*10+s-'0';s=getchar();} return x*f; } int n; int a[100007]; inline int max(int a,int b) {return a>b?a:b;} struct node{ int a,b; }e[100007*20]; int tot=1; inline void build(int x) { int p=1; for(int i=30;i>=0;i--) { int tmp=x&(1<<i); if(tmp) if(!e[p].a) e[p].a=++tot,p=tot; else p=e[p].a; else if(!e[p].b) e[p].b=++tot,p=tot; else p=e[p].b; } } inline int query(int x) { int p=1; int ans=0; for(int i=30;i>=0;i--) { int tmp=x&(1<<i); if(!tmp) { if(e[p].a) p=e[p].a,ans+=(1<<i); else p=e[p].b; } else { if(e[p].b) p=e[p].b; else p=e[p].a,ans+=(1<<i); } } return ans^x; } int main() { while(scanf("%d",&n)==1) { memset(e,0,sizeof(e)); int ans=-0x3f3f3f3f; for(int i=1;i<=n;++i) a[i]=read(); for(int i=1;i<=n;++i) build(a[i]); for(int i=1;i<=n;++i) ans=max(ans,query(a[i])); printf("%d\n",ans); } return 0; }
異或最大值