143. 最大异或对 AcWing

原题链接

字典树模板题

错误思路:

       很容易看出枚举两个数字必定TLE,但这题求最值必须枚举一个数,因此我们可以在枚举第二个数进行优化

正确思路:

       在枚举第二个数时,将第一个数的每一位分开贪心求解,将范围内的数全部插入字典数中,查询是否能获得高位尽量与第一个数相反的数

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 const int N = 1e5+10;
 5 const int M = 31*N;
 6 int idx,son[M][2],a[N];
 7 void insert(int x)//从最高位开始插入
 8 {//每个数字都被分解为30位二进制数,因此不需要标记数组
 9     int p = 0;
10     for(int i=30;~i;i--){
11         int t = x>>i&1;//x>>k&1获得x的第k位数字
12         if(!son[p][t]) son[p][t] = ++idx;
13         p = son[p][t];//获得结点下标
14     }
15 }
16 int query(int x)
17 {
18     int p = 0,ans = 0;
19     for(int i=30;~i;i--){
20         int t = x>>i&1;
21         if(son[p][!t]) { p = son[p][!t]; ans+= 1<<i; }
22         else p = son[p][t];
23     }
24     return ans;
25 }
26 int main()
27 {
28     int n,maxn = 1<<31;
29     scanf("%d",&n);
30     for(int i=1;i<=n;i++) { scanf("%d",&a[i]); insert(a[i]); }
31     for(int i=1;i<=n;i++){//第一步只能枚举,无法优化
32         int ans = query(a[i]);
33         maxn = max(ans,maxn);
34     }
35     printf("%d\n",maxn);
36     return 0;
37 }

 

posted @ 2021-01-01 14:07  acmloser  阅读(76)  评论(0编辑  收藏  举报