【Trie树】Ybt_最大异或对

题目大意

给你n个整数,要你任选两个,使它们的异或结果最大。输出这个结果。


从高位往低位处理,便于使异或结果最大。
构建Trie树。
从高位往地位处理,每次优先选与当前位不同的路径(这样和最大),若没有,就选择当前位相同的走下去。


代码

(易懂版本)

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
int n, m, len, w, f[10000009][3], A[1000009], ans, tot, k, l, lans;
char ch;
string s;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &A[i]);
        w = 0;//建一个0点用于出发...
        for (int j = 30; j >= 0; --j) {
            k = (A[i] >> j) % 2;  //取二进制下第j位的数字
            if (f[w][k] == 0) //w号点是否后面有连向的字符k?否。
                f[w][k] = ++tot;//新建一个点tot,w号点连点tot。(tot点代表k)
            w = f[w][k]; //走向下一个点
        }
    }
    for (int i = 1; i <= n; ++i) {
        w = lans = 0;
        for (int j = 30; j >= 0; --j) {
            k = (A[i] >> j) % 2;
            if (f[w][(k + 1) % 2] != 0) {  //选择不同的数字
                w = f[w][(k + 1) % 2];
                lans += 1 << j;  //加上当前位异或后能得到的值
            } else {
                if (f[w][k] != 0) //相同的数字
                    w = f[w][k];
                else //后面没有了
                    break;
            }
        }
        ans = max(ans, lans);  //取最大值
    }
    printf("%d", ans);
}

(优化版本)

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int n, m, len, w1, w2, f[10000009][3], A[1000009], ans, tot, flag, k, lans;
char ch;
string s;
int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%d", &A[i]);
		w1 = w2 = lans = flag = 0;
		for(int j = 30; j>=0; --j){
			k = (A[i] >> j) % 2;
			if(f[w1][k] == 0) f[w1][k] = ++tot;
			w1 = f[w1][k];
			if(flag == 0){
				if(f[w2][(k+1)%2] != 0) {
					w2 = f[w2][(k+1)%2];
					lans += 1 << j;
				} 
				else if(f[w2][k] != 0)
					w2 = f[w2][k];
				else flag = 1;
			}
		}
		ans = max(ans, lans);
	}
	printf("%d", ans);
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值