01字典树(待更新)

01字典树典型的题就是找出异或值最大的两个数,其实跟字典树差不多的,就是从原来的26位字母变成了0和1,插入操作也跟字典树差不多,查询的时候有贪心思想,尽量找同位不相同的。

模板:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6
 7 const int N=1e5+5;
 8
 9 struct node{
10     int next[2];
11     int val;
12     void reset(){
13         next[0]=next[1]=val=0;
14     }
15 }T[N*32];//数组大小为数字个数*最大位数
16
17 int cnt;//字典树上的节点个数
18
19 void init(){
20     cnt=0;
21     T[0].reset();
22 }
23
24 //将x插入到01字典树上
25 void insert(int x){
26     int cur=0;//从根节点开始
27     for(int i=31;i>=0;i--){
28         int t=(x>>i)&1;
29         if(!T[cur].next[t]){
30             //将下一个新节点初始化
31             T[++cnt].reset();
32             T[cur].next[t]=cnt;
33         }
34         cur=T[cur].next[t];
35     }
36     //插入x
37     T[cur].val=x;
38 }
39
40 //查询在字典树中查找和x异或的值最大的元素
41 int query(int x){
42     int cur=0;
43     for(int i=31;i>=0;i--){
44         int t=(x>>i)&1;
45         //贪心,尽量找不同的使异或值最大
46         if(T[cur].next[t^1])
47             cur=T[cur].next[t^1];
48         else
49             cur=T[cur].next[t];
50     }
51     return T[cur].val;
52 }

下面几道例题:

一、HDU 4825 xor sum

给你n个数,m次查询,输出n个数中与查询地数x异或值最大的数,模板题

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=1e5+5;

struct node{
    int next[2];
    int val;
    void reset(){
        next[0]=next[1]=val=0;
    }
}T[N*32];//数组大小为数字个数*最大位数 

int cnt;//字典树上的节点个数

void init(){
    cnt=0;
    T[0].reset();
} 

//将x插入到01字典树上
void insert(int x){
    int cur=0;//从根节点开始
    for(int i=31;i>=0;i--){
        int t=(x>>i)&1;
        if(!T[cur].next[t]){
            //将下一个新节点初始化
            T[++cnt].reset();
            T[cur].next[t]=cnt;
        }
        cur=T[cur].next[t];
    }
    //插入x
    T[cur].val=x;
}

//查询在字典树中查找和x异或的值最大的元素
int query(int x){
    int cur=0;
    for(int i=31;i>=0;i--){
        int t=(x>>i)&1;
        //贪心,尽量找不同的使异或值最大
        if(T[cur].next[t^1])
            cur=T[cur].next[t^1];
        else
            cur=T[cur].next[t];
    }
    return T[cur].val;
}

int main(){
    int t,cas=0;
    scanf("%d",&t);
    while(t--){
        init();
        int n,m,x;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            insert(x);
        }
        printf("Case #%d:\n",++cas);
        for(int i=1;i<=m;i++){
            scanf("%d",&x);
            printf("%d\n",query(x));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/fu3638/p/8136775.html

时间: 2024-10-03 20:06:40

01字典树(待更新)的相关文章

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 输入包含若干组测试数

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<st

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 发起

01字典树贪心查询+建立+删除(个人模版)

01字典树贪心查询+建立+删除: 1 #define maxn 2 2 typedef struct tree 3 { 4 tree *nex[maxn]; 5 int v; 6 int val; 7 }tree; 8 tree root; 9 void init() 10 { 11 for(int i=0;i<maxn;i++) 12 { 13 root.nex[i]=NULL; 14 } 15 } 16 void creat(char *str,int va) 17 { 18 int len

[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

HDU 4825 Xor Sum 【01字典树】

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

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

01字典树及其模板

模板 : const int Bit = 32; struct Trie { Trie *ch[2]; LL v; inline void init(){ for(int i=0; i<2; i++) this->ch[i] = NULL; this->v = -1; } }; Trie *root;///记得在 main 函数的时候分配空间给 root 并初始化 inline void CreateTrie(LL x) { Trie * p = root, *tmp; for(int