异或最大值(01字典树)

/**
异或最大值(01字典树)
题意:求n个非负数中任意2个的异或值的最大值。n数量级为10^5
分析:直接暴力肯定超时了。一个非负整数可以看成1个32位的01字符串,n个数可以看成n个字符串,因此可以建立字典树,
      建好树后,对于任意非负整数x,可以沿着树根往下贪心找到y,使得x异或y最大,复杂度为树的深度。
 */
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=3200010;
int n;
int a[100010];
int node;
int next[maxn][2];
int End[maxn];
void add(int cur, int k)
{
    memset(next[node],0,sizeof(next[node]));
    End[node]=0;
    next[cur][k]=node++;
}
int cal(int x)
{
    int k,cur=0;
    for(int i=30;i>=0;i--)
    {
        int k=!((1<<i)&x);
        if(next[cur][k])
            cur=next[cur][k];
        else
            cur=next[cur][k^1];
    }
    return (x^End[cur]);
}
int main()
{
    while(~scanf("%d",&n))
    {
        node=1;
        memset(next[0],0,sizeof(next[0]));
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            int x=a[i],cur=0;
            for(int j=30;j>=0;j--)
            {
                int k=((1<<j)&x);
                if(next[cur][k]==0)
                    add(cur,k);
                cur=next[cur][k];
            }
            End[cur]=x;
        }
        int ans=-1;
        for(int i=0;i<n;i++)
        {
            ans=max(ans,cal(a[i]));
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(异或最大值(01字典树))