Chip Factory---hdu5536(异或值最大,01字典树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5536

题意:有一个数组a[], 包含n个数,从n个数中找到三个数使得 (a[i]+a[j])⊕a[k]最大,i,j,k不同;

求异或的结果最大所以我们可以用01字典树,先把所有的数加入字典树中,从n个数中选出两个数a[i]和a[j],

先把他们从字典树中删除,然后找到与a[i]+a[j]异或最大的数,和结果取最大值即可;

最后不要忘记再把a[i]和a[j]添加到字典树中即可;

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define met(a, b) memset(a, b, sizeof(a))
#define N 1005
#define INF 0x3f3f3f3f
typedef long long LL;

struct node
{
    int num, sum;///num是当前的数,sum表示是否存在;
    node* Next[2];
};

void Add(node* head, int x, int cnt)
{
    node *p = head;///移动指针;
    for(int i=31; i>=0; i--)
    {
        int k = (x>>i)&1;///表示x对应的二进数从右边数第i位是k(0或1);
        if(p->Next[k] == NULL)///如果不存在就新建一个节点;
        {
            node* q = new node();
            p->Next[k] = q;
        }
        p = p->Next[k];///移动指针指向下一节点;
        p->sum += cnt;///当前节点可达;更新一下,如果是添加x则+1,删除x则-1;
    }
    p->num = x;///在结束的时候记录从head到当前位置所表示的数是x;
}
int Find(node* head, int x)
{
    node *p = head;
    for(int i=31; i>=0; i--)
    {
        int k = (x>>i)&1;
        if(p->Next[k^1] != NULL && p->Next[k^1]->sum > 0)///每次尽量往不同的方向走,前提是存在不同的节点;
            p = p->Next[k^1];
        else
            p = p->Next[k];
    }
    return (p->num^x);///最后找到的p->num就是与x异或最大的数;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n, a[N];
        node *head = new node();
        scanf("%d", &n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d", &a[i]);
            Add(head, a[i], 1);///添加所有的数到字典树中去;
        }
        int ans = 0;
        ///从n个数中选出两个数a[i]和a[j],先把他们从字典树中删除,
        ///然后找到与a[i]+a[j]异或最大的数,和结果取最大值即可;
        ///最后不要忘记再把a[i]和a[j]添加到字典树中即可;
        for(int i=1; i<=n; i++)
        {
            Add(head, a[i], -1);
            for(int j=1; j<=n; j++)
            {
                if(i==j)continue;
                Add(head, a[j], -1);
                int ret = Find(head, a[i]+a[j]);
                ans = max(ans, ret);
                Add(head, a[j], 1);
            }
            Add(head, a[i], 1);
        }
        printf("%d\n", ans);
    }
    return 0;
}

时间: 2024-10-29 19:06:43

Chip Factory---hdu5536(异或值最大,01字典树)的相关文章

Chip Factory(HDU5536 + 暴力 || 01字典树)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5536 题目: 题意: 对于给定的n个数,求出三个下标不同的数使得(si+sj)^sk最大. 思路: 由于时间给了9s,所以可以暴力过.不过还可以用01字典树艹过去,不过注意字典树里面存si查询(sj+sk),不要存(si+sj)查询sk,不然会T. 暴力代码实现如下: 1 #include <set> 2 #include <map> 3 #include <deque>

[01字典树]求序列完美度(求区间最大异或值)

https://nanti.jisuanke.com/t/15531 解题关键:01字典树模板,用字典树保存每个数的二进制表示,从而动态维护区间上的最大异或值,注意添加和删除都可以用于一个change函数表示. 复杂度:$O(n\log n + {n^2}\log n)$ 1 #include<bits/stdc++.h> 2 #define maxn 1005 3 #define inf 0x3f3f3f3f 4 using namespace std; 5 typedef long lon

利用01字典树查询最大异或值

01字典树的是只含有0和1两种字符的字典树,在使用它的时候,把若干数字转成二进制后插入其中 在查询树中的哪个数字和给定数字有最大异或值的时候,从根开始贪心查询就ok了 HDU4825是一道裸题:给出n个数和m次询问,每次询问给出一个数x,问在n个数中哪个数与x异或值最大 1 #include<cstdio> 2 #include<cstring> 3 const int maxn=1000005; 4 int n,m,rt; 5 int a[maxn],v[3500005],s[3

异或最大值(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

P4551 最长异或路径 (01字典树,异或前缀和)

题目描述 给定一棵 nn 个点的带权树,结点下标从 11 开始到 NN .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或. 输入输出格式 输入格式: 第一行一个整数 NN ,表示点数. 接下来 n-1n?1 行,给出 u,v,wu,v,w ,分别表示树上的 uu 点和 vv 点有连边,边的权值是 ww . 输出格式: 一行,一个整数表示答案. 输入输出样例 输入样例#1: 4 1 2 3 2 3 4 2 4 6 输出样例#1: 7 说明 最长异或序

HDU4825/5536 [01 字典树/简单字典树更新]

Xor Sum Time Limit: 1000 MS Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大.Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助.你能证明人类的智慧么? Input 输入包含若干组测试数

HDU6191(01字典树启发式合并)

Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 801    Accepted Submission(s): 302 Problem Description Monkey A lives on a tree, he always plays on this tree. One day, monkey

2014百度之星资格赛—— Xor Sum(01字典树)

Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total Submission(s): 0    Accepted Submission(s): 0 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起

HDU 4825 Xor Sum 【01字典树】

题面: Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大.Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助.你能证明人类的智慧么? Input 输入包含若干组测试数据,每组