143. 最大异或对

在给定的N个整数A1,A2……ANA1,A2……AN中选出两个进行xor(异或)运算,得到的结果最大是多少?

输入格式

第一行输入一个整数N。

第二行输入N个整数A1A1~ANAN。

输出格式

输出一个整数表示答案。

数据范围

1≤N≤1051≤N≤105,
0≤Ai<2310≤Ai<231

输入样例:

3
1 2 3

输出样例:

3
思路:
    每个数散成二进制存进tire树里边,找能和当前二进制xor成1的最大数字取最大值,只需要从跟走到叶节点就可以找到和当前数字最大的数了,这样的话每个数字最多走31位也就是总共的次数最多是31*100000,所以时间复杂度相当于nlogn

  



#include<iostream>

using namespace std;
//int 单个整数最大二进制是31个1,tire存储的每个分支数最多有31个节点
const int N = 1e5+10,M = 31*N;

int n;
int a[N];
//每个节点有01两种情况所以是2
int son[M][2],idx;

void insert(int x){
    int p = 0;
    for(int i = 30;i >= 0;i--)
    {
        //取第i位的二进制数是什么东西
        int u = x >> i & 1;
        if(!son[p][u]) son[p][u] = ++idx;
        p = son[p][u];
    }
}

int query(int x){
    int p = 0,res = 0;
    for(int i = 30;i >= 0;i--){
        int u = x >> i & 1;
        if(son[p][!u]){
            p = son[p][!u];
            res = res * 2 + !u;  

        } else{
            p = son[p][u];
            res = res * 2 + u;
        }
    }
    return res;
}
int main(){
    cin >> n;
    for(int i = 0;i < n;i++) cin >> a[i];

    int res = 0;
    //先插入,少一个判空的条件,所以先插入
    for(int i = 0;i < n;i++){
        insert(a[i]);
        int t = query(a[i]);
        res = max(res,a[i] ^ t);
    }

    cout << res;

}

  

原文地址:https://www.cnblogs.com/luyuan-chen/p/11632048.html

时间: 2024-09-29 15:47:18

143. 最大异或对的相关文章

143. 最大异或对(Trie树存整数+二进制)

在给定的N个整数A1,A2……ANA1,A2……AN中选出两个进行xor(异或)运算,得到的结果最大是多少? 输入格式 第一行输入一个整数N. 第二行输入N个整数A1A1-ANAN. 输出格式 输出一个整数表示答案. 数据范围 1≤N≤1051≤N≤105,0≤Ai<2310≤Ai<231 输入样例: 3 1 2 3 输出样例: 3 暴力做法:O(n^2) import java.util.Scanner; public class Main{ static int a[]=new int[1

AcWing 143. 最大异或对

https://www.acwing.com/problem/content/145 #include <iostream> #include <algorithm> using namespace std; const int N = 100010; int n; int a[N]; class TrieNode { public: TrieNode() {}; TrieNode* children[2]; }; class Trie { public: Trie() { roo

AcWing 143. 最大异或对 (异或性质,Trie)

? ? ? 刚开始WA了,数组又开小了,,关于字典树大小的问题,**考虑如果每一个字符都能生成新结点,那么字典树大小就是MAXN*LEN,本题目中数据是1<<31的范围,算上0位**就是32位长度字符串,即MAXN*32: 哦对还看到大佬写的是边插入边查询,这点没想到. #define int ll int a[MAXN]; int tot; int son[MAXN*32][2]; void build(int x) { int p=0; for(int k=32;k>=0;--k)

【GDKOI2016Day1T1-魔卡少女】【拆位】线段树维护区间内所有连续子区间的异或和

题意:给出N个数,M个操作.操作有修改和询问两种,每次修改将一个数改成另一个数,每次询问一个区间的所有连续子区间的异或和.n,m<=100000,ai<=1000 题解: 当年(其实也就是今年)做不出来的题..D1T1啊... 因为ai<=1000,我们可以拆位处理.拆成10个二进制位,每位开1棵线段树. 对于每个节点,维护: d:这段区间的异或和 L[0],L[1]:子区间一定从左端点开始,异或和为0,1的子区间分别有多少个 R[0],R[1]:子区间一定从右端点开始,异或和为0,1的

SWUST OJ 东6宿舍灵异事件(0322)

东6宿舍灵异事件(0322) Time limit(ms): 1000 Memory limit(kb): 65535 Submission: 88 Accepted: 31 Description 将军听说最近东6闹鬼了,作为一个无神论者,将军当然不相信.但是这个传言已经泛滥了,许多人都在说这个事情,将军从每个人那里听到一个传言,将军可以容易的就知道这个传言是真还是假,但是当一大堆消息组合起来,将军就不知道了,所以将军就找到了你. 提供两种组合方式: A&B:代表A和B都为真的时候,A和B组合

Trie树/字典树题目(2017今日头条笔试题:异或)

1 /* 2 本程序说明: 3 4 [编程题] 异或 5 时间限制:1秒 6 空间限制:32768K 7 给定整数m以及n各数字A1,A2,..An,将数列A中所有元素两两异或,共能得到n(n-1)/2个结果,请求出这些结果中大于m的有多少个. 8 输入描述: 9 第一行包含两个整数n,m. 10 11 第二行给出n个整数A1,A2,...,An. 12 13 数据范围 14 15 对于30%的数据,1 <= n, m <= 1000 16 17 对于100%的数据,1 <= n, m,

C的|、||、&amp;、&amp;&amp;、异或、~、!运算

位运算     位运算的运算分量只能是整型或字符型数据,位运算把运算对象看作是由二进位组成的位串信息,按位完成指定的运算,得到位串信息的结果. 位运算符有:     &(按位与).|(按位或).^(按位异或).~ (按位取反). 其中,按位取反运算符是单目运算符,其余均为双目运算符.     位运算符的优先级从高到低,依次为~.&.^.|, 其中~的结合方向自右至左,且优先级高于算术运算符,其余运算符的结合方向都是自左至右,且优先级低于关系运算符.    (1)按位与运算符(&) 

linux命令逻辑运算:与、或、非、异或

逻辑运算:与&.或|.非!.异或    与:只要有一个为假,结果一定为假    或:只要有一个为真,结果一定为真  1:真     0:假          1.与&      1 & 0 = 0    0 & 0 = 0 1 & 1 = 1    0 & 1 = 0    2.或      0|1 = 1    0|0 = 0 1|1 = 1    1|0 = 1 3.非!      !真 = 假    !假 = 真 4.异或      操作数相同则为假,

位运算之 C 与或非异或

位运算比较易混: 位运算之 C 与或非异或 与运算:& 两者都为1为1,否则为0 1&1=1,  1&0=0,  0&1=0,  0&0=0 或运算:| 两者都为0为0,否则为1 1|1 = 1,  1|0 = 1,  0|1 = 1, 0|0 = 0 非运算:~ 1取0,0取1 ~1 = 0, ~0 = 1 ~(10001) = 01110 异或运算:^ 两者相等为0,不等为1(易混淆) 1^1=0, 1^0=1, 0^1=1, 0^0=0 位移操作符:<&