可持久化fhq-treap学习笔记
可持久化fhq-treap----- 支持查询历史版本的非旋treap
luogu扣图:

先看看为啥他可以可持久化
由于fhq-Treap是没有旋转操作的
所以每次操作后的其它没有操作的节点间的关系不变
而有旋转平衡树是要改变的,所以就不大能进行可持久化了
过程
回想,主席树的方法:
每次用log的内存记录一次操作
这可持久平衡树也一样
每次merge或者split都新开节点记录路径
路径是log级的,所以内存也在nlogn的级别(当然不是nlog,是操作log)
还是用结构体吧,容易赋值
其实也就是加了几句话
其实也就是和主席树差不多
其实也没啥说的,看代码去吧
别的
SovietPower:一点(很小的)优化? 操作3.4.5.6都不会改原树,root[i]=root[ver]可以直接赋值,不需要再Merge了
xx:为什么
SovietPower:你的合并操作的内存都是新开的,但你这一次操作(是opt的操作辣)是没有改变任何值,所以你直接用上一次的就好,拆开的内存不用管就好
注意&&出错&&吐槽
我们截取merge函数的一部分
if(e[x].pri<e[y].pri) {
int p=++cnt;
e[p]=e[x];
rs(p)=merge(rs(p),y);
pushup(p);
return p;
}
}
那是不是可以写成
if(e[x].pri<e[y].pri) {
int p=++cnt;
e[p]=e[x];
rs(p)=merge(rs(p),y);
pushup(p);
return p;
}
当然是不对的啊,你还要递归呢,cnt当然要变化了
这数组模拟内存浪费的有点多呀,指针应该就没这毛病了,不过我还是学不下去指针233
模板->luoguP3835代码
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#define ls(x) e[x].ls
#define rs(x) e[x].rs
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=500007;
const int inf=0x7fffffff;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
struct node {
int ls,rs,size,val,pri;
}e[maxn*50];
int cnt,rt[maxn*50];
void pushup(int x) {
e[x].size=e[ls(x)].size+e[rs(x)].size+1;
}
int make_edge(int x) {
e[++cnt].val=x;
e[cnt].size=1;
e[cnt].pri=rand();
return cnt;
}
int merge(int x,int y) {
if(!x||!y) return x+y;
if(e[x].pri<e[y].pri) {
int p=++cnt;
e[p]=e[x];
rs(p)=merge(rs(p),y);
pushup(p);
return p;
}
else {
int p=++cnt;
e[p]=e[y];
ls(p)=merge(x,ls(p));
pushup(p);
return p;
}
}
void split(int now,int k,int &x,int &y) {
if(!now) x=y=0;
else {
if(e[now].val<=k) {
e[x=++cnt]=e[now];
split(rs(now),k,rs(x),y);
pushup(x);
}
else {
e[y=++cnt]=e[now];
split(ls(now),k,x,ls(y));
pushup(y);
}
}
}
inline int k_th(int now,int k) {
while(233) {
if(k==e[ls(now)].size+1) return now;
if(k<=e[ls(now)].size) now=ls(now);
else k-=e[ls(now)].size+1,now=rs(now);
}
}
int main() {
int n=read(),x,y,z;
FOR(i,1,n) {
int tim=read(),opt=read(),a=read();
rt[i]=rt[tim];
if(opt==1) {
split(rt[i],a,x,y);
rt[i]=merge(merge(x,make_edge(a)),y);
} else if(opt==2) {
split(rt[i],a,x,z);
split(x,a-1,x,y);
y=merge(ls(y),rs(y));
rt[i]=merge(merge(x,y),z);
} else if(opt==3) {
split(rt[i],a-1,x,y);
printf("%d\n",e[x].size+1);
rt[i]=merge(x,y);
} else if(opt==4) {
printf("%d\n",e[k_th(rt[i],a)].val);
} else if(opt==5) {
split(rt[i],a-1,x,y);
if(e[x].size) {
printf("%d\n",e[k_th(x,e[x].size)].val);
rt[i]=merge(x,y);
}
else printf("%d\n",-inf);
} else {
split(rt[i],a,x,y);
if(e[y].size) {
printf("%d\n",e[k_th(y,1)].val);
rt[i]=merge(x,y);
}
else printf("%d\n",inf);
}
}
return 0;
}
可持久化fhq-treap学习笔记的更多相关文章
- fhq treap 学习笔记
序 今天心血来潮,来学习一下fhq treap(其实原因是本校有个OIer名叫fh,当然不是我) 简介 fhq treap 学名好像是"非旋转式treap及可持久化"...听上去怪 ...
- FHQ treap学习(复习)笔记
.....好吧....最后一篇学习笔记的flag它倒了..... 好吧,这篇笔记也鸽了好久好久了... 比赛前刷模板,才想着还是补个坑吧... FHQ,这个神仙(范浩强大佬),发明了这个神仙的数据结构 ...
- 左偏树 / 非旋转treap学习笔记
背景 非旋转treap真的好久没有用过了... 左偏树由于之前学的时候没有写学习笔记, 学得也并不牢固. 所以打算写这么一篇学习笔记, 讲讲左偏树和非旋转treap. 左偏树 定义 左偏树(Lefti ...
- treap学习笔记
treap是个很神奇的数据结构. 给你一个问题,你可以解决它吗? 这个问题需要treap这个数据结构. 众所周知,二叉查找树的查找效率低的原因是不平衡,而我们又不希望用各种奇奇怪怪的旋转来使它平衡,那 ...
- fhq treap抄袭笔记
目录 碎碎念 点一下 注意!!! 模板 fhq treap 碎碎念 我咋感觉合并这么像左偏树呢 ps:难道你们的treap都是小头堆的吗 fhq真的是神人 现在看以前学的splay是有点恶心,尤其是压 ...
- Treap + 无旋转Treap 学习笔记
普通的Treap模板 今天自己实现成功 /* * @Author: chenkexing * @Date: 2019-08-02 20:30:39 * @Last Modified by: chenk ...
- [Treap][学习笔记]
平衡树 平衡树就是一种可以在log的时间复杂度内完成数据的插入,删除,查找第k大,查询排名,查询前驱后继以及其他许多操作的数据结构. Treap treap是一种比较好写,常数比较小,可以实现平衡树基 ...
- Treap-平衡树学习笔记
平衡树-Treap学习笔记 最近刚学了Treap 发现这种数据结构真的是--妙啊妙啊~~ 咳咳.... 所以发一发博客,也是为了加深蒟蒻自己的理解 顺便帮助一下各位小伙伴们 切入正题 Treap的结构 ...
- 「学习笔记」 FHQ Treap
FHQ Treap FHQ Treap (%%%发明者范浩强年年NOI金牌)是一种神奇的数据结构,也叫非旋Treap,它不像Treap zig zag搞不清楚(所以叫非旋嘛),也不像Splay完全看不 ...
- 「FHQ Treap」学习笔记
话说天下大事,就像fhq treap —— 分久必合,合久必分 简单讲一讲.非旋treap主要依靠分裂和合并来实现操作.(递归,不维护fa不维护cnt) 合并的前提是两棵树的权值满足一边的最大的比另一 ...
随机推荐
- ICMP报文
类型:表示ICMP消息类型 代码:表示同一消息的不同信息 其他是时间戳或者标识符及序列号 类型 编码 描述 0 0 Echo Reply 3 0 网络不可达 3 1 主机不可达 3 2 协议不可达 ...
- 【JMeter】如何优雅的写脚本
cc给发的视频链接: http://v.youku.com/v_show/id_XMzA4Mjg1ODA0MA==.html?spm=a2h3j.8428770.3416059.1 ————————— ...
- PHP消息队列实现及应用_慕课网学习
https://blog.csdn.net/d_g_h/article/details/79643714 https://blog.csdn.net/tTU1EvLDeLFq5btqiK/articl ...
- (Power Strings)sdutoj2475
#include <stdio.h>#include <string.h>#include <stdlib.h>char a[1000001];int next[1 ...
- js 使用jquery.form.js文件上传
1.文件上传,使用jquery.form.js插件库 <!DOCTYPE html> <html> <head> <meta charset="UT ...
- javascript实现unicode与字符互相转换
javascript实现unicode与字符互相转换. <script language="javascript"> //手机检测 function checkMo ...
- JS参差不齐的数组
<html><head> <title>参差不齐的数组</title> <meta charset="utf-8"> & ...
- thinkphp 隐藏表单验证原理
function savetoken() //创建session('hash') ,然后在魔板中表单中加入隐藏域 getsession('hash'),提交表单验证值是否一样,如果一样验证通过,同时重 ...
- python使用WSGI接口实现简单网页
Python Web 介绍 Python的Web服务器分为服务器程序和应用程序.服务器程序负责接收客户端的请求发送给应用程序,应用程序负责处理请求返回给服务器程序.为了方便应用程序的开发,我们把常用的 ...
- 25最短路径之Dijkstra算法
图的最优化问题:最小生成树.最短路径 典型的图应用问题 无向连通加权图的最小生成树 有向/无向加权图的最短路径 四个经典算法 Kruskal算法.Prim算法---------------最小生成树 ...