异或最大值 CSU - 1216 0-1字典树(0-1Trie)

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1216
题意:

给定一串数字(int范围内),求这些数字的两两最大异或值。

思路:

首先肯定可以暴力枚举,但是O(N^2)的时间复杂度太高,这道题应该使用字典树。将每个数分解成二进制串存储到字典树中,根在高位的方向,容易知道,这棵树的高度为32,每一层对应32位整数的一位。存储的同时去查询当前异或值的大小,经过比较记录最大的异或值。每次查询当前异或值的原则应该是尽量选择与自己当前位不同的路径,再通过一个变量rtn记录这个路径:每向下走一层,rtn就右移一位,如果当前位有与自己当前位相反的节点那么rtn就+1。
参考了某大佬的博客,图非常详细:https://blog.csdn.net/woshinannan741/article/details/51985368

代码:

#include <bits/stdc++.h>
#define fp(PP,QQ,RR) for(int PP = QQ;PP < RR;PP ++)
#define fs(PP,QQ,RR) for(int PP = QQ;PP >= RR;PP --)
#define MAXN 100005
using namespace std;
typedef long long ll;
struct trie{
    int trie[MAXN * 2][2],sz;
    void init(){
        memset(trie,0,sizeof(trie));
        sz = 0;
    }
    void insert(int t){
        int u = 0,w;
        for(int i = 31;i >= 0;i --){
            w = (t >> i) & 1;
            if(!trie[u][w]) trie[u][w] = ++ sz;
            u = trie[u][w];
        }
    }
    int find(int t){
        int u = 0,w,rtn = 0;
        for(int i = 31;i >= 0;i --){
            w = 1 - (t >> i) & 1;
            rtn <<= 1;
            if(trie[u][w]){
                rtn ++;
                u = trie[u][w];
            }else{
                u = trie[u][w ^ 1];
            }
        }
        return rtn;
    }

}tr;
int main(void)
{
    int n;
    while(scanf("%d",&n) != EOF){
        tr.init();
        int ans = 0,tmp;
        fp(i,0,n){
            cin >> tmp;
            tr.insert(tmp);
            ans = max(ans,tr.find(tmp));
        }
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值