版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Leon_liuqinburen/article/details/78273683
参照了别人的板子http://blog.csdn.net/solardomo/article/details/52168853 ,然后做了几个水题,稍微综合了一下01字典树板子
不用关心代码内部是如何实现的
只将01字典树看做是一个数集 我们可以在这个集合中查找和X异或最大的元素\异或最小值
板子练习题
https://nanti.jisuanke.com/t/15531
http://codeforces.com/contest/706/problem/D
http://acm.hdu.edu.cn/showproblem.php?pid=4825
https://vjudge.net/problem/LightOJ-1269
const int MAXN = 1000 + 5;
struct Trie
{
///如果是LL 则需要改成64 * 数组元素个数
/// 下面的for也是如此 需要改成 i = 64
int ch[32 * MAXN][2]; //节点的边信息
int num[32 * MAXN]; //节点存储值的个数
LL value[32 * MAXN]; //节点存储的值
int node_cnt; //树中当前节点个数
void init() //树清空
{
node_cnt = 1;
memset(ch[0],0,sizeof(ch));
memset(num, 0, sizeof(num));
}
void Insert(LL x, int d) //在字典树中插入d个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];
num[cur] += d;
}
value[cur] = x; //最后的节点插入value
}
void update(LL x, int d) //更新x的个数 d为浮动值 可正可负
{
int cur = 0;
for(int i = 32 ; i >= 0 ; i--)
{
int idx = (x >> i) & 1;
cur = ch[cur][idx];
num[cur] += d;
}
}
LL Query(LL x, int dir) //在字典树中查找和X异或的最大值\最小值的元素Y 返回Y的值 dir为1表示寻找异或最大值,为0表示寻找最小值
{
int cur = 0;
for(int i = 32; i >= 0; --i)
{
int idx = (x >> i) & 1;
if(ch[cur][idx ^ dir] && num[ch[cur][idx ^ dir]]) cur = ch[cur][idx ^ dir];
else cur = ch[cur][idx ^ !dir];
}
return value[cur];
}
};