【维护异或和】 最大异或对

传送门

题意

给定\(N\)个整数\(A_{1}、A_{2}、\dots A_{n}\),从中选出两个进行异或运算求最大值

数据范围

\(\begin{array}{l}1 \leq N \leq 10^{5} \\ 0 \leq A_{i}<2^{31}\end{array}\)

题解

将数字的二进制\(01\)串作为字符串建立字典树,建立长度为\(30\)\(01\)字符串,每次查询时,贪心的从高位开始,
每次都将与当前的二进制位不同的计算代表的二进制数字,累加即此数字能够得到的最大值
字典树的长度为\(10^{5} \times 30\) ,在极端情况下每个数字的二进制都不同,每一个数字的二进制有\(30\)

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)

const int N=1e5+10;
int trie[N*30][2],tot=1;

void insert(int x)
{  
    int p=1;
    per(i,0,31)
    {
        int u=x>>i&1;
        if(!trie[p][u]) trie[p][u]=++tot;
        p=trie[p][u];
    }
}
int query(int x)
{
    int p=1;
    int res=0;
    per(i,0,31)
    {
        int u=x>>i&1;
        if(trie[p][!u]) 
        {
            res+=1<<i;
            p=trie[p][!u];
        }
        else p=trie[p][u];
    }
    return res;
}
void solve()
{
    int n;
    cin>>n;
    int ans=-1e6;
    rep(i,0,n)
    {
        int x;
        cin>>x;
        insert(x);
        ans=max(ans,query(x));
    }
    cout<<ans<<endl;
}

int main()
{
    solve();
}
posted @ 2020-07-28 08:35  Hyx'  阅读(189)  评论(0编辑  收藏  举报