之前一直不把Trie当回事,直到今天看了篇博客,据说01trie可以当平衡树使?然后就学了学,发现和权值线段树也没什么区别
01Trie
权值线段树的本质是一棵01Trie
01Trie就是把数字的二进制位从高到低当做字符串扔进Trie里
巨佬一眼就能看出,把最高位是0的当做左儿子,最高位是1的当做右儿子,这玩意就是权值线段树。
只是01Trie的边界有一些特性其实权值线段树也能实现,可以用来做一些按位运算的题。当然,权值线段树能实现的所有功能它都能实现。
例题:【模板】普通平衡树
做法:就和权值线段树做法是一样的。这题中平衡树能实现的功能01Trie也都能实现
妈妈再也不用教我写平衡树了
好吧平衡树还是有独特的功能的,比如区间翻转。
方法就和权值线段树实现一样。
感觉代码硬生生地比splay少了rotate和splay函数。
应该很好懂的 自认码风比较友好
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int Q = 1e7;
struct tree
{
int ch[2], size, end;
};
struct Trie
{
tree b[4000005];
int cnt;
Trie()
{
memset(b, 0, sizeof(b));
cnt = 1;
}
void insert(int x)
{
int p = 1;
for(int i = 30; i >= 0; i--)
{
int f = ((x & (1 << i)) >> i);
if(!b[p].ch[f])b[p].ch[f] = ++cnt;
p = b[p].ch[f]; b[p].size++;
}
b[p].end++;
}
void del(int x)
{
int p = 1;
for(int i = 30; i >= 0; i--)
{
int f = ((x & (1 << i)) >> i);
if(!b[p].ch[f])b[p].ch[f] = ++cnt;
p = b[p].ch[f]; b[p].size--;
}
b[p].end--;
}
int get_sum(int x)
{
int p = 1;
for(int i = 30; i >= 0; i--)
{
int f = ((x & (1 << i)) >> i);
p = b[p].ch[f];
if(!p)return 0;
}
return b[p].end;
}
int get_rank(int x)
{
int ret = 0, p = 1, tmp = 0;
for(int i = 30; i >= 0; i--)
{
int f = ((x & (1 << i)) >> i)