异或最大值

1、1216: 异或最大值

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1216

Time Limit: 2 Sec Memory Limit: 128 Mb

Description

给定一些数,求这些数中两个数的异或值最大的那个值

Input

多组数据。第一行为数字个数n,1 <= n <= 10 ^ 5。接下来n行每行一个32位有符号非负整数。

Output

任意两数最大异或值

Sample Input

3
3
7
9

Sample Output

14

Hint

Source
CSGrandeur的数据结构习题

思路:

暴力\(N^2\)

贪心一下

xor 即不同为1,相同为0

如果一个数a去找能得到 最大异或值 的b

(我也搞不清楚哪里是最高位了,就把最右边当第一位吧)

二进制较高位不同的数字一定比他们二进制较高位相同的异或值大

比如 有三个数 10 6 8

10的二进制是1010

6的二进制是0101

8的二进制是1000

则和10异或值最大的就是8(第4位比较)

贪心好了

下面就该实现了

二进制无非就0和1

要快速查找,就可以建一个01字典树

比如这样

当范围大到int也最多有30层 时间复杂度\(nlogn\)

考试居然忘了输出\n了,我TM真的是,╮(╯▽╰)╭ 哎

/*
                       ▍ ★∴
  ....▍▍....█▍ ☆ ★∵ ..../
  ◥█▅▅██▅▅██▅▅▅▅▅███◤
   .◥███████████████◤
~~~~◥█████████████◤~~~~
*/
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

inline int read()
{
    int x=0,f=1;char s=getchar();
    while('0'>s||s>'9') {if(s=='-')f=-1;s=getchar();}
    while('0'<=s&&s<='9') {x=x*10+s-'0';s=getchar();}
    return x*f;
}

int n;
int a[100007];

inline int max(int a,int b) {return a>b?a:b;}

struct node{
    int a,b;
}e[100007*20];
int tot=1;

inline void build(int x)
{
    int p=1;
    for(int i=30;i>=0;i--) {
        int tmp=x&(1<<i);
        if(tmp)
            if(!e[p].a)
                e[p].a=++tot,p=tot;
            else p=e[p].a;
        else
            if(!e[p].b) e[p].b=++tot,p=tot;
            else p=e[p].b;
    }
}

inline int query(int x)
{
    int p=1;
    int ans=0;
    for(int i=30;i>=0;i--) {
        int tmp=x&(1<<i);
        if(!tmp) {
            if(e[p].a) p=e[p].a,ans+=(1<<i);
            else p=e[p].b;
        }
        else {
            if(e[p].b)  p=e[p].b;
            else p=e[p].a,ans+=(1<<i);
        }
    }
    return ans^x;
}

int main()
{
    while(scanf("%d",&n)==1) {
        memset(e,0,sizeof(e));
        int ans=-0x3f3f3f3f;
        for(int i=1;i<=n;++i)
            a[i]=read();
        for(int i=1;i<=n;++i)
            build(a[i]);
        for(int i=1;i<=n;++i)
            ans=max(ans,query(a[i]));
        printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lovedsr/p/9319770.html

时间: 2024-10-11 16:43:15

异或最大值的相关文章

中南大学COJ 1216: 异或最大值(数据结构)

中南大学COJ 1216: 异或最大值(数据结构) ACM 题目地址:COJ 1216 题意: 中文题,注意是多组样例. 分析: 用01Trie做的. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: coj1216.cpp * Create Date: 2014-07-27 14:18:44 * Descripton: trie */ #include <cstdio> #include <cstring>

异或最大值(01字典树)

/** 异或最大值(01字典树) 题意:求n个非负数中任意2个的异或值的最大值.n数量级为10^5 分析:直接暴力肯定超时了.一个非负整数可以看成1个32位的01字符串,n个数可以看成n个字符串,因此可以建立字典树, 建好树后,对于任意非负整数x,可以沿着树根往下贪心找到y,使得x异或y最大,复杂度为树的深度. */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iost

CSU 1216 异或最大值

[题意] 给定序列q[1..n],求任意两数异或的最大值 数据范围:1<=n<=10^5,q[i]为32位非负整数 [分析]Trie用来从高到低保存0和1,然后爆搜:尽可能凑1,不然凑0 [代码] WOC为什么是多组数据? #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; const int K=32; const int L=3300000; typed

Poj The xor-longest Path 经典题 Trie求n个数中任意两个异或最大值

Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5646   Accepted: 1226 Description In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p: ⊕ is the xor operator. We say a path the xor-l

CSU 1216异或最大值

Description 给定一些数,求这些数中两个数的异或值最大的那个值 Input 多组数据.第一行为数字个数n,1 <= n <= 10 ^ 5.接下来n行每行一个32位有符号非负整数. Output 任意两数最大异或值 Sample Input 3 3 7 9 Sample Output 14 Hint Source CSGrandeur的数据结构习题 异或 异或运算符(^ 也叫xor(以后做题会遇到xor,就是异或)) 规则:0^0 = 0,0^1=1,1^0=1,1^1=0 参加位运

bzoj3261: 最大异或和 可持久化trie

题意:给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类型: 1.Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1. 2.Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得: a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. 题解:可持久化trie 用前缀异或来建树,查询就变成了last^x和l到r中a[p]异或最大值是多少 先插入一个0,然后像可持久化线段树那样建树即可,还是挺简单的 /**

[十二省联考2019]异或粽子 (可持久化01tire 堆)

/* 查询异或最大值的方法是前缀和一下, 在01trie上二分 那么我们可以对于n个位置每个地方先求出最大的数, 然后把n个信息扔到堆里, 当我们拿出某个位置的信息时, 将他去除当前最大后最大的信息插入到堆中 所以动态维护01trie就可以了 */ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #define mm

[luogu] P4551 最长异或路径(贪心)

P4551 最长异或路径 题目描述 给定一棵\(n\)个点的带权树,结点下标从\(1\)开始到\(N\).寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或. 输入输出格式 输入格式: 第一行一个整数\(N\),表示点数. 接下来 \(n-1\) 行,给出 \(u,v,w\) ,分别表示树上的 \(u\) 点和 \(v\) 点有连边,边的权值是 \(w\). 输出格式: 一行,一个整数表示答案. 输入输出样例 输入样例#1: 复制 4 1 2 3 2

【题解】Luogu P5283 [十二省联考2019]异或粽子

原题传送门 看见一段的异或和不难想到要做异或前缀和\(s\) 我们便将问题转化成:给定\(n\)个数,求异或值最靠前的\(k\)对之和 我们珂以建一个可持久化01trie,这样我们就珂以求出每个值\(s[a]\)与之前所有的值异或值最大的值\(b\)是多少,把这些所有\((b,a)\)塞进一个堆中 每次从堆顶取元素,设这个元素为\((b,a)\),要将\(b\)加入答案,并且在版本\(a\)的01trie中减去\(s[a]\)^\(b\),再取出\(s[a]\)与01trie中的数异或最大值(原