2017西安交大ACM小学期 有趣异或[Trie树]

有趣异或

发布时间: 2017年7月4日 23:59   最后更新: 2017年7月5日 14:56   时间限制: 1500ms   内存限制: 512M

描述

给定n个非负整数,保证这些数两两不相同。现给定x,请从中选2个不同的数a,b,使得a^b^x最大。

输入

包含多组测试数据。
每组测试数据第一行有1个正整数和1个非负整数,分别为nx
接下来一行有n个正整数。
所有数据满足n106,所有非负整数以及x小于等于109
总数据量n106

输出

对每组数据输出一行1个整数,表示a^b^x的最大值是多少。

样例输入1 
复制

3 0
1 2 3

样例输出1

3

首先,我们把所有的整数对应的二进制前面补0,补成30位的二进制数,然后把这串二进制数当成字符串,存入Trie树中。

其次,我们遍历所有的数a,然后我们寻找b,使得a^b^x最大

我们这样分析,当a和x确定时候a^x也就确定了设a^x = t

那么欲使t^b最大,那么t与b的相同的位上,值应该尽可能的不同,所以,我们依据t的位,在Trie中寻找b。。。

这里有一个坑点,那就只注意a和b不能相同,如果数据是x = (1111111….)b的话,那么朴素的求会找到与a相等的b,这显然是错误的

因此,可以用一个标记,代表当前搜索到的Trie树位置是否可能得到与a相等的b,搜索时候注意就好了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 1e6+7;
int n,x;
int a[MAX];
struct trie
{
    int count;
    trie* child[2];
};
trie* root;
void build(int num){
    trie* p = root;
    for(int i = 29;i >= 0;i--){
        int key = (num>>i) & 1;
        if(!p -> child[key]){
            trie* nt = new trie;
            nt -> count = 1;
            nt -> child[0] = nt -> child[1] = 0;
            p -> child[key] = nt;
            p = nt;
        }
        else{
            p = p -> child[key];
            p -> count ++;
        }
    }
} 
int find(int a){
    int res = 0;
    trie* p = root;
    int able = 1;
    for(int i = 29;i >= 0;i--){
        int f = (x>>i) & 1;
        if(f){
            int key = (a>>i) & 1;
            if(!p->child[key]) {
                //没有相同位 
                able = 0;
                key ^= 1; 
            }else{
                //有相同位 
                if(!able){
                    //已经不可能.直接选 
                    res |= (1<<i); 
                }
                else{
                    //还可能 
                    if(p->child[key]->count-1 == 0){
                        //不能选
                        able = 0;
                        key ^= 1; 
                    }
                    else{
                        //可以选
                        // todo	
                        res |= (1<<i);		 
                    }
                }
            }
            p = p -> child[key];
        }
        else{
            //最好不同   
            int key = (a>>i) & 1 ^ 1;
            //key 为理想  
            if(p->child[key]){
                //有不同位 
                able = 0;
                res |= (1<<i);
            }
            else{
                //只有相同位 
                key ^= 1;
            }
            p = p -> child[key];
        }
    }
    return res;
}
int main(){
    while(~scanf("%d%d",&n,&x)){
        int ma = 0;
        root = new trie;
        root -> count = 0; root -> child[0] = root -> child[1] = 0;
        for(int i = 0;i < n;i++){
            scanf("%d",&a[i]);
            build(a[i]);
        }
        for(int i = 0;i < n;i++){
            ma = max(ma,find(a[i]));
        }
        printf("%d\n",ma);
    }
    return 0;
} 

    原文作者:Trie树
    原文地址: https://blog.csdn.net/weixin_37517391/article/details/74935808
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞