这一次,我们来了解普通Trie树的变种:0-1Trie以及在其基础上产生的可持久化Trie(其实,普通的Trie也可以可持久化,只是不太常见)

先简单介绍一下0-1Trie:一个0-1Trie节点只有两个子节点,分别代表0和1;从根节点开始,第一层代表限制的最高位,依次往下直到最底层,代表二进制第0位。

0-1Trie上的一条链所表示的数字,就是Trie树中的一个数字。0-1Trie除了节点和插入方式与普通的Trie树略有不同之外,其他操作都是和Trie树完全一样的。在维护这个节点插入过的数的个数size之后,0-1Trie甚至可以做一些平衡树的题……

下面给2道比较简单的例题:

bzoj3689 异或之 http://www.lydsy.com/JudgeOnline/problem.php?id=3689

bzoj3224 普通平衡树 http://www.lydsy.com/JudgeOnline/problem.php?id=3224

值得注意的是,0-1Trie无法处理负权值,因此,我们可以给每个数加上一个大的修正值delta,使得所有值都成为非负的。最后我们在减去delta即可。

下面给出0-1Trie版的普通平衡树代码,很短,但是的确可以AC:

 #include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int inf=0x7fffffff,delta=;
LL bin[];
struct Trie
{
Trie *ch[];int size;
Trie(){size=;ch[]=ch[]=NULL;}
}*null=new Trie(),*root;
inline Trie* newTrie(){Trie *o=new Trie();o->ch[]=o->ch[]=null;return o;}
inline void insert(int x)
{
Trie *rt=root;
for(int i=;~i;i--)
{
int d=(x&bin[i])>>i;
if(rt->ch[d]==null)rt->ch[d]=newTrie();
rt=rt->ch[d],rt->size++;
}
}
inline void del(int x)
{
Trie *rt=root;
for(int i=;~i;i--)
rt=rt->ch[(x&bin[i])>>i],rt->size--;
}
inline int getrank(int x)
{
Trie *rt=root;int ret=;
for(int i=;~i;i--)
{
if((x&bin[i])>>i)ret+=rt->ch[]->size;
rt=rt->ch[(x&bin[i])>>i];
}
return ret;
}
inline int getval(int rank)
{
Trie *rt=root;int ret=;
for(int i=;~i;i--)
{
if(rt->ch[]->size>=rank)rt=rt->ch[];
else rank-=rt->ch[]->size,ret|=bin[i],rt=rt->ch[];
}
return ret;
}
int main()
{
bin[]=;for(int i=;i<=;i++)bin[i]=bin[i-]<<;
root=newTrie();null->ch[]=null->ch[]=null;
int m,opt,x;scanf("%d",&m);
while(m--)
{
scanf("%d%d",&opt,&x);
switch(opt)
{
case :insert(x+delta);break;
case :del(x+delta);break;
case :printf("%d\n",getrank(x+delta)+);break;
case :printf("%d\n",getval(x)-delta);break;
case :printf("%d\n",getval(getrank(x+delta))-delta);break;
case :printf("%d\n",getval(getrank(x+delta+)+)-delta);break;
}
}
}

接下来,我们在0-1Trie的基础上,介绍可持久化Trie。

可持久化Trie树和前面两种可持久化数据结构一样,也是通过复制节点来实现可持久化操作。

在插入的时候,我们也是复制路径上的节点,由于可持久化Trie和主席树一样具有区间可减性,所以我们直接像主席树那样区间相减即可。

具体代码,长得和之前的可持久化Treap差不多……下面给出插入的代码(可能比较丑……)

 //bin[i]数组为预处理的2的i次方
void insert(Trie *&o,Trie *old,int val,int i)
{
if(i<)return;
int d=((val&bin[i])==bin[i]);//判断当前为是0还是1
o->ch[d]=newTrie();o->ch[d^]=old->ch[d^];
o->ch[d]->size=old->ch[d]->size+;
insert(o->ch[d],old->ch[d],val,i-);
}

可持久化Trie树经常用来处理与异或有关的k小问题。一般来说,我们都是把0-1Trie可持久化来维护数字运算,很少有把字符串的Trie可持久化的题目。

这里再给出两道可持久化Trie的基础题:

bzoj4103[Thu Summer Camp 2015]异或运算 http://www.lydsy.com/JudgeOnline/problem.php?id=4103

我的题解:http://www.cnblogs.com/LadyLex/p/7281945.html

bzoj3166[Heoi2013]Alo http://www.lydsy.com/JudgeOnline/problem.php?id=3166

我的题解:http://www.cnblogs.com/LadyLex/p/7281860.html

可持久化Trie是一种和主席树同样优秀的数据结构,无疑是一种新的解题思路。希望大家能从我的博客中有所收获:)

[您有新的未分配科技点]可,可,可持久化!?------0-1Trie和可持久化Trie普及版讲解的更多相关文章

  1. [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 ...

  2. [您有新的未分配科技点]博弈论进阶:似乎不那么恐惧了…… (SJ定理,简单的基础模型)

    这次,我们来继续学习博弈论的知识.今天我们会学习更多的基础模型,以及SJ定理的应用. 首先,我们来看博弈论在DAG上的应用.首先来看一个小例子:在一个有向无环图中,有一个棋子从某一个点开始一直向它的出 ...

  3. [您有新的未分配科技点]博弈论入门:被博弈论支配的恐惧(Nim游戏,SG函数)

    今天初步学习了一下博弈论……感觉真的是好精妙啊……希望这篇博客可以帮助到和我一样刚学习博弈论的同学们. 博弈论,又被称为对策论,被用于考虑游戏中个体的预测行为和实际行为,并研究他们的应用策略.(其实这 ...

  4. [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...

  5. [您有新的未分配科技点]数位DP:从板子到基础(例题 bzoj1026 windy数 bzoj3131 淘金)

    只会统计数位个数或者某种”符合简单规律”的数并不够……我们需要更多的套路和应用 数位dp中常用的思想是“分类讨论”思想.下面我们就看一道典型的分类讨论例题 1026: [SCOI2009]windy数 ...

  6. [您有新的未分配科技点]数位dp:从懵X到板子(例题:HDU2089 不要62)

    数位dp主要用来处理一系列需要数数的问题,一般套路为“求[l,r]区间内满足要求的数/数位的个数” 要求五花八门……比如“不出现某个数字序列”,“某种数的出现次数”等等…… 面对这种数数题,暴力的想法 ...

  7. [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树

    这次我们来搞一个很新奇的知识点:克鲁斯卡尔重构树.它也是一种图,是克鲁斯卡尔算法求最小生成树的升级版首先看下面一个问题:BZOJ3545 Peaks. 在Bytemountains有N座山峰,每座山峰 ...

  8. Prism5.0新内容 What's New in Prism Library 5.0 for WPF(英汉对照版)

    Prism 5.0 includes guidance in several new areas, resulting in new code in the Prism Library for WPF ...

  9. Elasticsearch 学习之 分片未分配原因

    分片未分配的原因主要有: 1)INDEX_CREATED:由于创建索引的API导致未分配.2)CLUSTER_RECOVERED :由于完全集群恢复导致未分配.3)INDEX_REOPENED :由于 ...

随机推荐

  1. 打开 EXCEL时出现RUN-TIME ERROR“91”,怎么解决?

    方法一: 开始—程序—microsoft—打开“windows office 2007 简易设置”,把“使用 office 03样式经典菜单”前的“√”去掉就OK了 方法二: 1. 打开注册表编辑器. ...

  2. Linux的crontab

    如果要让unix系统重复,定期做一件事,我们就会用到crontab. 实质上真正去执行每一个重复任务的是cron,cron是的unix家族的一个后台常驻程序,cron是由cron文件来驱动的,cron ...

  3. MAC nginx代理设置

    问题: 10.154.156.83:10081私服不存在了.但是不能改.用nginx代理至maven.xx.cn 增加换回地址: sudo ifconfig lo0 add 10.154.156.83 ...

  4. 2018-2019-1 20189215《Linux内核原理与分析》第三周作业

    <庖丁解牛>第二章书本知识总结 函数调用框架 call指令有两个作用: (1) 将CS:EIP中下一条指令的地址A保存在栈顶: (2)设置CS:EIP指向被调用程序的第一行. ret指令在 ...

  5. 2017-2018-1 JaWorld 第四、五周作业

    2017-2018-1 JaWorld 第四.五周作业 两周工作内容 小组讨论并确定最终的app雏形 合作完成需求说明书 工作分工 成员 分工 比例 陈是奇 1.引言 8% 马平川 2.1-2.5 产 ...

  6. fiddler几种功能强大的用法(二)

    参考网址:http://blog.rekfan.com/articles/228.html http://www.cnblogs.com/tugenhua0707/p/4637771.html htt ...

  7. lxml.etree去除子节点

    去除etree中的某个子节点有两种方法: 1.parentnode.remove(node) 2.etree.strip_elements(html, 'element_name', with_tag ...

  8. 一次完整的HTTP事务是怎样一个过程

    当我们在浏览器的地址栏输入 www.linux178.com,然后回车,回车这一瞬间到看到页面到底发生了什么呢? 以下过程仅是个人理解: 域名解析 --> 发起TCP的3次握手 --> 建 ...

  9. 字符编码_Windows资料

    1. 1.1.MSDN 函数WideCharToMultiByte(...) https://msdn.microsoft.com/en-us/library/windows/desktop/dd37 ...

  10. Linux命令详解-help

    help命令顾名思义就是显示帮助信息的,它是个Bash内建命令,也只是用来显示Bash内建命令的帮助信息的(Display  helpful  information about builtin co ...