范浩强treap——可持久化
当平衡树需要可持久化的时候,意味着我们需要访问以前的某个时间点的平衡树,就要保持以前的树形态不变,新建一个时间戳,构建一棵新的树。
如果用以前的旋转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——可持久化的更多相关文章
- 范浩强treap 普通平衡树
增加Split(分裂),Merge(合并)操作,非常好写,时间也不比普通treap慢什么. #include<bits/stdc++.h> using namespace std; str ...
- 旷视6号员工范浩强:高二开始实习,“兼职”读姚班,25岁在CVPR斩获第四个世界第一...
初来乍到,这个人说话容易让人觉得"狂". "我们将比赛结果提交上去,果不其然,是第一名的成绩."当他说出这句话的时候,表情没有一丝波澜,仿佛一切顺理成章. 他说 ...
- 挂羊头卖狗肉蓄意欺骗读者——谭浩强《C程序设计(第四版)》中所谓的“按照C99”(二)
挂羊头卖狗肉蓄意欺骗读者——谭浩强<C程序设计(第四版)>中所谓的“按照C99”(二) 在<谭C>p4:“本书的叙述以C99标准为依据”,下面从C89到C99的主要变化方面来看 ...
- C语言学习笔记---谭浩强
前段时间有机会去面试了一次,真是备受“打击”(其实是启发),总的来说就是让我意识到了学习工具和学习技术的区别.所以最近在看一些数据结构和算法,操作系统,python中的并行编程与异步编程等东西.然而数 ...
- C指针笔试题,蛋疼的多重指针运算,谭浩强的阴影
对指针的概念清晰的话,做这种题只要耐心就行,然而看这种题就烦(被同学吐槽为谭浩强的阴影……草泥马这种C风格题有意义吗?出题人脑子被门夹了?而且C++11都不支持字面值字符串直接转换成char*了.好吧 ...
- c++面向对象程序设计 课后题 答案 谭浩强 第四章
c++面向对象程序设计课后题答案 谭浩强 第四章 1: #include <iostream> using namespace std; class Complex {public: Co ...
- c++面向对象程序设计 谭浩强 第三章答案
2: #include <iostream> using namespace std; class Date {public: Date(int,int,int); Date(int,in ...
- c++面向对象程序设计 谭浩强 第二章答案
类体内定义成员函数 #include <iostream> using namespace std; class Time { public: void set_time(); void ...
- c++面向对象程序设计 谭浩强 第一章答案
c++面向对象程序设计 谭浩强 答案 第一章 目录: c++面向对象程序设计 谭浩强 答案 第一章 c++面向对象程序设计 谭浩强 答案 第二章 c++面向对象程序设计 谭浩强 答案 第三章 c++面 ...
随机推荐
- mysql数据库 批量替换 某字段中的数据
当数据库出现这种情况: 表名:area id name 1 太仓 2 太仓市 3 太仓市 ... ... 我需要把 name字段中 的太仓市 的“市“去掉 可以使用: update `area` ...
- ActiveMQ 与 Spring
1. ActiveMQ安装 1.1 下载(版本5.14.5) 点我官网下载 1.2 安装 解压下载的压缩文件到任意目录中(eg. C:\Program Files (x86)\apache-activ ...
- 洛谷 Sorting a Three-Valued Sequence 三值的排序
Description 排序是一种很频繁的计算任务.现在考虑最多只有三值的排序问题.一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌序的时候. 在这个任务中可能的值只有三种1,2和3.我们用交换的 ...
- NYOJ 1272 表达式求值 第九届省赛 (字符串处理)
title: 表达式求值 第九届省赛 nyoj 1272 tags: [栈,数据结构] 题目链接 描述 假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式. 2. 如果 X 和 Y 是 表 ...
- vue安装说明
1.安装node.js(http://www.runoob.com/nodejs/nodejs-install-setup.html) --以下操作在nodejs安装路径下进行(记得不要在C盘)-- ...
- python模块之imghdr检测图片类型
1. imghdr是什么 imghdr是一个用来检测图片类型的模块,传递给它的可以是一个文件对象,也可以是一个字节流. 能够支持的图片格式: 2. 如何使用 提供了一个api叫做imghdr.what ...
- 爬虫--PySpider框架
PySpider框架 PySpider框架的作用
- Linux Deploy 使用 Repository部署Linux系统
Linux Deploy 使用 Repository部署Linux系统 为了解决镜像不稳定导致包下载错误,能得到一个稳定环境,可以使用linux deploy导出功能. 这里提供两个制作好的包 用户名 ...
- RF, GBDT, XGB区别
GBDT与XGB区别 1. 传统GBDT以CART作为基分类器,xgboost还支持线性分类器(gblinear),这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回 ...
- php中的转义函数
<?php parse_url 解析URL, 返回各组成部分 urlencode/urldecode url编码/解码 htmlentities 将字符串转化为html实体 htmlentiti ...