zoukankan      html  css  js  c++  java
  • 最大异或对

    题目传送:https://www.acwing.com/problem/content/description/145/

    在给定的N个整数A1,A2……AN<?XML:NAMESPACE PREFIX = "[default] http://www.w3.org/1998/Math/MathML" NS = "http://www.w3.org/1998/Math/MathML" />A1,A2……AN中选出两个进行xor(异或)运算,得到的结果最大是多少?

    输入格式

    第一行输入一个整数N。

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

    输出格式

    输出一个整数表示答案。

    数据范围

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

    输入样例:
    3
    1 2 3
    输出样例:
    3

    暴力是最简单的解题办法。这题先拿暴力来写。
      1 #include <iostream>
      2 #include <algorithm>
      3 using namespace std;
      4 const int N = 1e6 + 5;
      5 int a[N];
      6 
      7 int main() {
      8 	int n;
      9 	cin >> n;
     10 	for(int i = 0; i < n; ++ i)
     11 		cin >> a[i];
     12 	int res = 0;
     13 	for(int i = 0; i < n; ++ i)
     14 		for(int j = 0; j < n; ++ j)
     15 			if(i != j)
     16 				res = max(res, a[i]^a[j]);
     17 	cout << res << endl;
     18 	return 0;
     19 }


    这种方法往往是,会带来完美的TLE。当然优化的方法就要通过观察,可以通过什么数据结构将复杂度降下来。

    先观察暴力做法,循环的第一次是没法优化的,观察第二层循环,重复多次求最大值,这显然不是最优的。

    先来了解异或,当两个二进制对应位上的值都不相同时就异或值就会最大。

    这样看来我们只需要只找它与枚举的数,的二进制尽可能相反。在众多的数据结构中,字典树可以满足这个要求。

    我们把每位数都当成32位二进制数,不够的补0.然后通过策略,每次都取对应位相反的数,否子取相同的。

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <string>
      4 using namespace std;
      5 const int N = 1e5 + 5, M = 31 * N;
      6 
      7 int n;
      8 int a[N];
      9 int trie[M][2], tot;
     10 
     11 void insert(int x) { // 通过每个数的二进制来构建字典树,每个节点就只有两个指针 
     12 	int p = 0;
     13 	for (int i = 31; i >= 0; -- i)
     14 	{
     15 		int u = x >> i&1;//取对应的位置的数 
     16 		if(!trie[p][u]) trie[p][u] = ++ tot;
     17 		p = trie[p][u];
     18 	}
     19 }
     20 
     21 int query(int x) {
     22 	int p = 0, res = 0;
     23 	for(int i = 31; i >= 0; -- i) {//每个数都当成二进制位,存储 
     24 		int u = x >> i & 1;
     25 		if(trie[p][!u])//最优策略是走相反的路。 
     26 		{
     27 			p = trie[p][!u];
     28 			res = res*2 + 1;//对应位置相反,则res*2 + 1就相当于0-1 -> 1 ,*2相当于向左移动一位。 
     29 		}
     30 		else {
     31 			p = trie[p][u];// 
     32 			res = res * 2 + 0;
     33 		}
     34 	}
     35 	return res;
     36 }
     37 
     38 int main() {
     39 	cin >> n;
     40 	for(int i = 0; i < n; ++ i)
     41 	{
     42 		cin >> a[i];
     43 		insert(a[i]);
     44 	}
     45 
     46 	int res = 0;
     47 	for(int i = 0; i < n; ++ i) {
     48 		res = max(res, query(a[i]));
     49 	}
     50 	cout << res << endl;
     51 	return 0;
     52 }
    追求吾之所爱
  • 相关阅读:
    正则表达式中匹配中文
    计算机中的颜色——颜色概述
    人物系列Claude Shannon
    reading listfrom other blog
    how to write Makefile
    《麻省理工大学开放课程:线性代数》[中英双语字幕]视频下载
    正则表达式30分钟入门教程
    usage of fscanf and other read functions in C/C++
    《麻省理工大学开放课程:线性代数》学习
    Open review of papers
  • 原文地址:https://www.cnblogs.com/rstz/p/14391010.html
Copyright © 2011-2022 走看看