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[100005];
          public static void main(String[] args) {
                Scanner scan=new Scanner(System.in);
                int n=scan.nextInt();
                for(int i=0;i<n;i++) a[i]=scan.nextInt();
                int max=-1;
                  for(int i=0;i<n;i++)
                      for(int j=0;j<i;j++)
                          max=Math.max(max, a[i]^a[j]);
                  System.out.println(max);

        }
}
对此步做优化
 for(int i=0;i<n;i++)
     for(int j=0;j<i;j++)//----这一步
        max=Math.max(max, a[i]^a[j]);
O(n*logn)

异或运算,同为0,不同为1

建立trie树,左0右1

先插入一个整数,然后查询,查询过程中,如果u是1,就尽可能往0那边走;如果u是0,就尽可能往1那边走

AC代码:
import java.util.Scanner;

public class Main{
        static final int N=100005,M=N*31;
        static int a[]=new int[N];
        static int son[][]=new int [M][2];
        static int idx=0;
        static void insert(int x){
                int p=0;
                for(int i=30;i>=0;i--){
                        int u=x>>i&1;
                        if(son[p][u]==0) son[p][u]=++idx;
                        p=son[p][u];
                }
        }
        static int query(int x){
                int p=0,res=0;
                for(int i=30;i>=0;i--){
                        int u=x>>i&1;
                        //如果u是1,就尽可能往0那边走;如果u是0,就尽可能往1那边走
                        if(son[p][u==1?0:1]!=0){
                                p=son[p][u==1?0:1];
                                res=res*2+(u==1?0:1);//加括号,优先级问题
                        }
                        else{
                                p=son[p][u];
                                res=res*2+u;
                        }
                }
                return res;
        }
        public static void main(String[] args) {
                 Scanner scan=new Scanner(System.in);
                 int n=scan.nextInt();
                 for(int i=0;i<n;i++) a[i]=scan.nextInt();
                 int res=0;
                 for(int i=0;i<n;i++){
                         insert(a[i]);
                         int num=query(a[i]);
                         res=Math.max(res, a[i]^num);
                 }
                 System.out.println(res);
        }
}

原文地址:https://www.cnblogs.com/qdu-lkc/p/12234248.html

时间: 2024-10-08 18:51:06

143. 最大异或对(Trie树存整数+二进制)的相关文章

BZOJ 3689 异或之 Trie树+堆

题目大意:给定n个数,求这n个数两两异或的值中的前k小 首先我们对所有数字建立二进制Trie树,可以利用Trie树上的size域查询出一个数与其它数异或值的第k小 然后我们维护一个堆,将所有数与其它异或值的第2小加入堆(第一小是自己异或自己,不在题目要求范围内),当取出一个数异或值的第k小后,将第k+1小加入堆 一个异或值会被两个数分别取出一次,所以取出奇数次时输出,取2*k次即可 时间复杂度O(nlogn) #include<cstdio> #include<cstring> #

Nikitosh 和异或 —— 一道 trie 树的题用可持久化 trie 水 然后翻车了...

题意简介 题目就是叫你找两个不重合的非空区间,使得这两个区间里的数异或后相加的和最大 (看到异或,没错就决定是你了可持久化trie!) 思路 水一波字典树,莫名觉得这题可持久化能过,于是水了一发挂了,造了一波数据,然后发现是自己在做完一遍可持久化之后cnt 没有清零.... 其实要用可持久化trie 来做的话也就是常规操作(话说普通字典树不也是常规操作?) 也就是前缀和往可持久化trie 上update , 然后每个 L[i].R[i] 记录当前点为右(左)区间的最大区间异或和 然后就是枚举断点

【bzoj1174】[Balkan2007]Toponyms Trie树

题目描述 给你一个字符集合,你从其中找出一些字符串出来. 希望你找出来的这些字符串的最长公共前缀*字符串的总个数最大化. 输入 第一行给出数字N.N在[2,1000000] 下面N行描述这些字符串,长度不超过20000 .保证输入文件不超过10MB 输出 a single line with an integer representing the maximal level of complexity Lc(T). 样例输入 7 Jora de Sus Orhei Jora de Mijloc

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,

【bzoj3281】最大异或和 可持久化Trie树

题目描述 给定一个非负整数序列 {a},初始长度为 N.       有M个操作,有以下两种操作类型:1.A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1.2.Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. 输入 第一行包含两个整数 N  ,M,含义如问题描述所示.   第二行包含 N个非负整数,表示初始的序列 A . 接下来 M行,每行描述一个

[bzoj3261]最大异或和[可持久化trie树]

因为要求异或和最大,所以可以考虑从高位开始,向低位枚举尽可能接近~x的值,所以以二进制位为关键字,建立可持久化trie树,根据异或和的性质,XOR_SUM{i,j}=XOR_SUM{1,j} xor XOR_SUM{1,i-1},所以查询问题也可以解决了. 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <c

【BZOJ3689】异或之 堆+可持久化Trie树

[BZOJ3689]异或之 Description 给定n个非负整数A[1], A[2], ……, A[n].对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数.求这些数(不包含A[i])中前k小的数.注:xor对应于pascal中的“xor”,C++中的“^”. Input 第一行2个正整数 n,k,如题所述.以下n行,每行一个非负整数表示A[i]. Output 共一行k个数,表示前k小的数. Samp

bzoj 3261: 最大异或和 (可持久化trie树)

3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MB Description 给定一个非负整数序列 {a},初始长度为 N.       有   M个操作,有以下两种操作类型: 1 .A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1.2 .Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得: a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. Inp

XJOI 异或 (Trie树)

这题对我来说真是一块大蛋糕,又是一座大山 大蛋糕是因为算法很好胡 大山是因为我实在是太菜 然后我就在考场上续了两个小时 /-------------------------------------------/ 这题算法不算难想,但对我来说挺难打 1.将ai拆成二进制,由高位到低位加入Trie树,不足的补前导0,每个节点的ans统计子树中有多少个值 2.读入区间l,r拆成区间1-r+1,1-l处理 3.search时统计小于limit的数量 4.如果pos的一个子树内异或x最大值之差小于limi