当平衡树需要可持久化的时候,意味着我们需要访问以前的某个时间点的平衡树,就要保持以前的树形态不变,新建一个时间戳,构建一棵新的树。

如果用以前的旋转treap可能就不方便做到(又要打时间戳,又要新建节点,又要旋转),而且涉及到旋转,空间可能会承受不住,我们需要用到一种新的平衡树——fhq treap

这是一种非常好写的treap 核心操作有两个,一个是split一个是merge。

split(node,k,x,y) 意思是把以node为跟的子树分成两部分,一部分小于等于k(根为x),一部分大于k(根为y)。在可持久化的时候要保证以前的树的形态不变,就要每一次copy一个节点过来。

而我们每一次递归只会访问一个节点的左右子树中的一个节点,又因为treap的均摊深度为log,所以总体的空间为nlogn,是非常高效的。

说完split接下来是merge

merge函数,是有返回值的,merge(x,y) 是把以x为根的子树和以y为根的子树合并起来,返回这棵新的树的根,递归的实现,非常好懂。

接下来的所有操作都是基于以上两个核心的操作,非常好理解,比旋转的treap好理解而且更好写,注意可持久化即可。

——by VANE

 #include<bits/stdc++.h>
using namespace std;
const int N=;
struct node
{
int ch[];
int fix,key,sz;
}t[N*];
int root[N],cnt=;
int copynode(int x)
{
cnt++;
t[cnt]=t[x];
return cnt;
}
void update(int cur)
{
if(cur)
t[cur].sz=t[t[cur].ch[]].sz+t[t[cur].ch[]].sz+;
}
int newnode(int val)
{
cnt++;
t[cnt].ch[]=t[cnt].ch[]=;
t[cnt].key=val;
t[cnt].sz=;
t[cnt].fix=rand();
return cnt;
}
void split(int now,int k,int &x,int &y)
{
if(!now) x=y=;
else
{
if(t[now].key<=k)
{
x=copynode(now);
split(t[x].ch[],k,t[x].ch[],y);
}
else
{
y=copynode(now);
split(t[y].ch[],k,x,t[y].ch[]);
}
update(x);
update(y);
}
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
if(t[x].fix<t[y].fix)
{
int r=copynode(x);
t[r].ch[]=merge(t[r].ch[],y);
update(r);
return r;
}
else
{
int r=copynode(y);
t[r].ch[]=merge(x,t[r].ch[]);
update(r);
return r;
}
}
void insert(int bb,int val)
{
int x,y,z;
x=y=z=;
split(root[bb],val,x,y);
z=newnode(val);
root[bb]=merge(merge(x,z),y);
}
void Delete(int bb,int val)
{
int x,y,z;
split(root[bb],val,x,z);
split(x,val-,x,y);
y=merge(t[y].ch[],t[y].ch[]);
root[bb]=merge(merge(x,y),z);
}
int getpos(int now,int k)
{
while()
{
if(k<=t[t[now].ch[]].sz) now=t[now].ch[];
else if(k==t[t[now].ch[]].sz+) return now;
else k-=t[t[now].ch[]].sz+,now=t[now].ch[];
}
}
int getkth(int bb,int val)
{
int x,y;
int ret;
split(root[bb],val-,x,y);
ret=t[x].sz+;
return ret;
}
int getval(int now,int k)
{
int x;
x=getpos(now,k);
return t[x].key;
}
int getpre(int bb,int val)
{
int x,y;
int k,ret;
split(root[bb],val-,x,y);
if(x) k=t[x].sz;
else return -;
ret=getval(x,k);
return ret;
}
int getnext(int bb,int val)
{
int x,y;
split(root[bb],val,x,y);
if(!y) return ;
int ret=getval(y,);
return ret;
}
int main()
{
int n,bb,cmd,val;
scanf("%d",&n);
for(int i=;i<=n;++i)
{
scanf("%d%d%d",&bb,&cmd,&val);
root[i]=root[bb];
switch(cmd)
{
case :insert(i,val);break;
case :Delete(i,val);break;
case :printf("%d\n",getkth(i,val));break;
case :printf("%d\n",getval(root[i],val));break;
case :printf("%d\n",getpre(i,val));break;
case :printf("%d\n",getnext(i,val));break;
}
}
}

范浩强treap——可持久化的更多相关文章

  1. 范浩强treap 普通平衡树

    增加Split(分裂),Merge(合并)操作,非常好写,时间也不比普通treap慢什么. #include<bits/stdc++.h> using namespace std; str ...

  2. 旷视6号员工范浩强:高二开始实习,“兼职”读姚班,25岁在CVPR斩获第四个世界第一...

    初来乍到,这个人说话容易让人觉得"狂". "我们将比赛结果提交上去,果不其然,是第一名的成绩."当他说出这句话的时候,表情没有一丝波澜,仿佛一切顺理成章. 他说 ...

  3. 挂羊头卖狗肉蓄意欺骗读者——谭浩强《C程序设计(第四版)》中所谓的“按照C99”(二)

    挂羊头卖狗肉蓄意欺骗读者——谭浩强<C程序设计(第四版)>中所谓的“按照C99”(二) 在<谭C>p4:“本书的叙述以C99标准为依据”,下面从C89到C99的主要变化方面来看 ...

  4. C语言学习笔记---谭浩强

    前段时间有机会去面试了一次,真是备受“打击”(其实是启发),总的来说就是让我意识到了学习工具和学习技术的区别.所以最近在看一些数据结构和算法,操作系统,python中的并行编程与异步编程等东西.然而数 ...

  5. C指针笔试题,蛋疼的多重指针运算,谭浩强的阴影

    对指针的概念清晰的话,做这种题只要耐心就行,然而看这种题就烦(被同学吐槽为谭浩强的阴影……草泥马这种C风格题有意义吗?出题人脑子被门夹了?而且C++11都不支持字面值字符串直接转换成char*了.好吧 ...

  6. c++面向对象程序设计 课后题 答案 谭浩强 第四章

    c++面向对象程序设计课后题答案 谭浩强 第四章 1: #include <iostream> using namespace std; class Complex {public: Co ...

  7. c++面向对象程序设计 谭浩强 第三章答案

    2: #include <iostream> using namespace std; class Date {public: Date(int,int,int); Date(int,in ...

  8. c++面向对象程序设计 谭浩强 第二章答案

    类体内定义成员函数 #include <iostream> using namespace std; class Time { public: void set_time(); void ...

  9. c++面向对象程序设计 谭浩强 第一章答案

    c++面向对象程序设计 谭浩强 答案 第一章 目录: c++面向对象程序设计 谭浩强 答案 第一章 c++面向对象程序设计 谭浩强 答案 第二章 c++面向对象程序设计 谭浩强 答案 第三章 c++面 ...

随机推荐

  1. 10个基于 JavaScript 的 WYSIWYG 编辑器

    COMSHARP CMS 写道:在线编辑内容的时候,那些基于 JavaScript 的编辑器帮了我们大忙,这些所见即所得(WYSIWYG)编辑器,给我们提供了类似 Office 的操作体验.如今,任何 ...

  2. HDFS默认副本数为什么是3

    转载自: https://www.cnblogs.com/bugchecker/p/why_three_replications_for_HDFS_in_engineer.html HDFS采用一种称 ...

  3. 【BZOJ】1066: [SCOI2007]蜥蜴

    [算法]网络流-最大流(dinic) [题解] 构图思路: 因为石柱高度是可以被消耗的,即一根石柱可通过的蜥蜴数量有限,取舍问题中这样表示容量的属性显然可以作为网络流中的边. 于是将一根石柱拆成顶部和 ...

  4. 【CodeForces】576 D. Flights for Regular Customers

    [题目]D. Flights for Regular Customers [题意]给定n个点m条边的有向图,每条边有di表示在经过该边前必须先经过di条边,边可重复经过,求1到n的最小经过边数.n,m ...

  5. Node.js的开源博客系统Ghost搭建教程

    准备工作 Node.js版本:0.10.x.0.12.x.4.2.x.安装步骤可参考:Node.js环境搭建 Ghost版本:0.7.4:中文集成版(33.6M),中文标准版(3.39M),英文原版( ...

  6. CodeForces 869B

    Even if the world is full of counterfeits, I still regard it as wonderful. Pile up herbs and incense ...

  7. 在Linux上安装pycharm

    1.首先在官网下载pycharm并进行提取,将提取的文件夹放在/usr下面(或者任意位置) 2.然后vi /etc/hosts 编辑 将0.0.0.0 account.jetbrains.com添加到 ...

  8. windows下phpstrom中xdebug的使用

    https://laravel-china.org/articles/16425/windows-phpstorm-xdebug-breakpoint-debugging

  9. [ python ] 作业:选课系统

    功能代码实现源地址:https://www.cnblogs.com/lianzhilei/p/5832691.html    如有侵权,立即删除 本文主要是分析 选课系统 实现思路及上面代码的实现过程 ...

  10. 4、GitLab 创建、删除、修改项目

    一.gitLab创建项目 1.创建用户组 2.填写组信息后单击“Create group” 其中:“Group path”将显示在git路径中 3.选择需要加入该组的“用户”和“角色”后点击“Add ...