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 i=Bit; i>=0; i--){
        int idx = (x>>i)&1;
        if(p->ch[idx] == NULL){
            tmp = (Trie *)malloc(sizeof(Trie));
            tmp->init();
            p->ch[idx] = tmp;
        }//else  //加个权值啥的
        p = p->ch[idx];
    }
    p->v = x;///在结尾打上标记,表示这串二进制的十进制表示是多少
}

LL Query(LL x)
{
    Trie *p = root;
    for(int i=Bit; i>=0; i--){
        int idx = (x>>i)&1;
        if(p->ch[idx^1]){
            p = p->ch[idx^1];
        }else p = p->ch[idx];
    }
    return p->v;
}

inline void DelTrie(Trie *T)
{
    if(T == NULL) return ;
    for(int i=0; i<2; i++){
        if(T->ch[i]){
            DelTrie(T->ch[i]);
        }
    }free(T);
}

指针版

const int maxn = 100000 + 5;        //集合中的数字个数
typedef long long LL;
int ch[32 * maxn][2];               //节点的边信息
LL value[32 * maxn];                //节点存储的值
int node_cnt;                       //树中当前节点个数

inline void init(){                 //树清空
    node_cnt = 1;
    memset(ch[0],0,sizeof(ch));
}
inline void Insert(LL x){           //在字典树中插入 X
                                    //和一般字典树的操作相同 将X的二进制插入到字典树中
    int cur = 0;
    for(int i = 32;i >= 0;--i){
        int idx = (x >> i) & 1;
        if(!ch[cur][idx]){
            memset(ch[node_cnt],0,sizeof(ch[node_cnt]));
            ch[cur][idx] = node_cnt;
            value[node_cnt++] = 0;
        }
        cur = ch[cur][idx];
    }
    value[cur] = x;                 //最后的节点插入value
}
LL Query(LL x){              //在字典树中查找和X异或的最大值的元素Y 返回Y的值
    int cur = 0;
    for(int i = 32;i >= 0;--i){
        int idx = (x >> i) & 1;
        if(ch[cur][idx ^ 1]) cur = ch[cur][idx ^ 1];
        else cur = ch[cur][idx];
    }
    return value[cur];
}

数组版

01字典树是求区间连续的异或和以及异或最大值的有利工具

参考博客 ==>

http://blog.csdn.net/guhaiteng/article/details/52191831

http://blog.csdn.net/solardomo/article/details/52168853

http://blog.csdn.net/miracle_ma/article/details/51484054

相关题目 :

时间: 2024-08-03 22:01:16

01字典树及其模板的相关文章

Vasiliy&#39;s Multiset CodeForces -706D || 01字典树模板

就是一个模板 注意这题有一个要求:有一个额外的0一直保持在集合中 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int _LEN=30; 5 //上限为2^30-1,即二进制最多30位 6 int lft[40]; 7 namespace Trie 8 { 9 int ch[7001000][2],sz[7001000]; 10 int mem; 11 void insert(int

cf842D 01字典树|线段树 模板见hdu4825

一般异或问题都可以转换成字典树的问题,,我一开始的想法有点小问题,改一下就好了 下面的代码是逆向建树的,数据量大就不行 /*3 01字典树 根据异或性质,a1!=a2 ==> a1^x1^..^xn != a2^x1^..an 把修改转换成不同的询问 先把初始集合里没有的数建立成字典树 每次询问找的是字典树里异或x最小的值 */ #include<bits/stdc++.h> using namespace std; #define maxn 300005 int buf[maxn];

[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字典树典型的题就是找出异或值最大的两个数,其实跟字典树差不多的,就是从原来的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 n

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

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

HDU 4825 Xor Sum 【01字典树】

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