[Trie] 最大异或对

题目:

给定一数组,  求一对位置 i, j 且有arr[i] ^ arr[j]值最大, 输出最大值


解法:

暴力求肯定不妥,

所以需要一种快速的存储此前所有数字的数据结构

并通过异或贪心求出最大值

简单推导:

异或, 不进位加法, 同零异一

所以当前位置的最优解即为此前所有数字中, 与当前数二进制位相异的最多且最优即为解

最优很简单, 从高位到低位不同最优, 高位的权重大,这个很好理解

所以可以用trie储存此前数的二进制位并贪心求解

 代码


/*
	Zeolim - An AC a day keeps the bug away
*/

//pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <sstream>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef long double ld;
const ld PI = acos(-1.0);
const ld E = exp(1.0);

const int MAXN = 2e7 + 10;

int trie[MAXN][2] = {0}, cnt = 1;

void insert(ll x)
{
	int to = 1;

	for(int i = 31; i >= 0; --i)
	{
		int val = (x >> i) & 1;
		if(!trie[to][val])
			trie[to][val] = ++cnt;
		to = trie[to][val];
	}
}

ll rfind(ll x)
{

	ll ret = 0;

	int to = 1;

	for(int i = 31; i >= 0; --i)
	{
		int val = ((x >> i) & 1) ^ 1;

		if(!trie[to][val])
			to = trie[to][val ^ 1];
		else
			to = trie[to][val], ret = ret + (1 << i);
	}

	return ret;
}

int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0);     cout.tie(0);
    //freopen("D://test.in", "r", stdin);
    //freopen("D://test.out", "w", stdout);
    
    ll n, x, ans = 0;

    cin >> n;

    for(int i = 0; i < n; ++i)
    {
    	cin >> x;
    	if(i)
    		ans = max(ans, rfind(x));
    	insert(x);
    }

    cout << ans << '\n';

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Zeolim/article/details/89101825