这一次,我们来了解普通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. poj3071 Football(概率dp)

    poj3071 Football 题意:有2^n支球队比赛,每次和相邻的球队踢,两两淘汰,给定任意两支球队相互踢赢的概率,求最后哪只球队最可能夺冠. 我们可以十分显然(大雾)地列出转移方程(设$f[ ...

  2. dependencyManagement、parent与dependencies

    本文总结自:https://www.cnblogs.com/feibazhf/p/7886617.html 当我们的项目很多时,为了适应子项目的依赖项使用统一的版本,我们可以创建一个parent项目来 ...

  3. sqlite的bool字段

    简直被坑死了, bool字段更新,只能用0或1,才是正确的更新. 否则select出来的字段是错的 本来用true和false更新的,更新之后,使用sqliteexpert查看,更新结果是对的. 但是 ...

  4. 寻找List之和的最近素数

    Task : Given a List [] of n integers , find minimum mumber to be inserted in a list, so that sum of ...

  5. Codeforces Round #319 (Div. 2) B. Modulo Sum 抽屉原理+01背包

    B. Modulo Sum time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  6. QtWebKit_cookie

    1.百度搜索“qtwebkit cookie” 2. 2.1.qtwebkit 里 cookie 信息的保存 http://blog.tianya.cn/post-227188-33378112-1. ...

  7. 使用ARouter遇到的坑

    跨模块跳转不能跳转 需要被跳转的模块或者说使用了ARouter注解的模块都要加上这个 dependencies{    annotationProcessor rootProject.ext.arou ...

  8. spark + cassandra +postgres +codis 大数据方案

    1.环境: 1.1.cassandra 集群: 用于日志数据存储 1.2.spark集群: 用户后期的实时计算及批处理 1.3.codis 集群: 用于缓存一些基本数据如IP归属地,IP经纬度等,当日 ...

  9. [Kafka] - Kafka Java Consumer实现(二)

    Kafka提供了两种Consumer API,分别是:High Level Consumer API 和 Lower Level Consumer API(Simple Consumer API) H ...

  10. js将 HTML 页面生成 PDF 并下载

    最近碰到个需求,需要把当前页面生成 pdf,并下载.弄了几天,自己整理整理,记录下来,我觉得应该会有人需要 :) 先来科普两个插件: html2Canvas 简介 我们可以直接在浏览器端使用html2 ...