今天上午学了一下fhq treap感觉真的很好用啊qwq

  • 变量名解释:

    • \(size[i]\)表示以该节点为根的子树大小
    • \(fix[i]\)表示随机权值
    • \(val[i]\)表示该节点的值
    • \(ch[i][0]\)表示该节点的左儿子
    • \(ch[i][1]\)表示该节点的右儿子
  • 更新操作:update
inline void update(int x)
{size[x]=1+size[ch[x][0]]+size[ch[x][1]];}

就是用自己的左右子树更新自己。

  • 新建节点:new_node
inline int new_node(int x)
{
size[++cnt]=1;
val[cnt]=x;
fix[cnt]=rand();
return cnt;
}
  • 分裂操作:split
inline void split(int now,int k,int &x,int &y)
{
if(!now) x=y=0;
else
{
if(val[now]<=k) x=now,split(ch[now][1],k,ch[now][1],y);
else y=now,split(ch[now][0],k,x,ch[now][0]);
update(now);
}
}

x,y分别表示左右子树的根节点。

刚开始肯定是要初始化为0的。

之后因为分裂之后now这个点是在左子树里面的,所以如果val[now]<=k的话,当前点的左子树肯定要归到左子树里,但是右子树里的点不确定,递归求解右子树。

val[now]>k的话道理相似。

  • 合并操作:merge
inline int merge(int A,int B)
{
if(!A||!B) return A+B;
if(fix[A]<fix[B])
{
ch[A][1]=merge(ch[A][1],B);
update(A);
return A;
}
else
{
ch[B][0]=merge(A,ch[B][0]);
update(B);
return B;
}
}

返回值是合并之后树的根节点。

我们比较他们的随机权值,如果B大,就把A的右子树和B进行合并。如果A大,就把A和B的左子树进行合并。

注意因为传入参数的时候A这棵树的权值默认是小于B的,所以顺序不要写反了qwq.......

  • 求一棵树\((now)\)中排名第\(k\)个的数的节点编号:kth
inline int kth(int now,int k)
{
while(1)
{
if(k<=size[ch[now][0]]) now=ch[now][0];
else if(k==size[ch[now][0]]+1) return now;
else k-=size[ch[now][0]]+1,now=ch[now][1];
}
}
  • 求k的全局排名:rnk
inline int rnk(int a)
{
split(root,a-1,x,y);
int res=size[x]+1;
root=merge(x,y);
return res;
}
  • 插入节点:in
inline void in(int a)
{
split(root,a,x,y);
root=merge(merge(x,new_node(a)),y);
}
  • 删除节点:del
inline void del(int a)
{
split(root,a,x,z);
split(x,a-1,x,y);
y=merge(ch[y][0],ch[y][1]);
root=merge(merge(x,y),z);
}
  • 求前驱: pre
inline int pre(int a)
{
split(root,a-1,x,y);
int res=val[kth(x,size[x])];
root=merge(x,y);
return res;
}

分裂之后很明显x中都小于等于a,求前继的话就可以直接输出x中最大数了。

  • 求后继: nxt
inline int nxt(int a)
{
split(root,a,x,y);
int res=val[kth(y,1)];
root=merge(x,y);
return res;
}

分裂之后y中的都大于a,所以直接输出y中的第一个就可以了qwq

最后以一个普通平衡树的模板AC代码来结尾吧。。。

代码对fhq封装了一下qwq

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<ctime>
inline int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
namespace fhq
{
#define MAXN 500010
int x,y,z,root,cnt;
int size[MAXN],val[MAXN],ch[MAXN][2],fix[MAXN];
inline void update(int x){size[x]=1+size[ch[x][0]]+size[ch[x][1]];}
inline int new_node(int x){size[++cnt]=1;val[cnt]=x;fix[cnt]=rand();return cnt;}
inline int merge(int A,int B)
{
if(!A||!B) return A+B;
if(fix[A]<fix[B]){ch[A][1]=merge(ch[A][1],B);update(A);return A;}
else {ch[B][0]=merge(A,ch[B][0]);update(B);return B;}
}
inline void split(int now,int k,int &x,int &y)
{
if(!now) x=y=0;
else{
if(val[now]<=k) x=now,split(ch[now][1],k,ch[now][1],y);
else y=now,split(ch[now][0],k,x,ch[now][0]);
update(now);
}
}
inline int kth(int now,int k){while(1){
if(k<=size[ch[now][0]]) now=ch[now][0];
else if(k==size[ch[now][0]]+1) return now;
else k-=size[ch[now][0]]+1,now=ch[now][1];}
}
inline int rnk(int a){split(root,a-1,x,y);int res=size[x]+1;root=merge(x,y); return res;}
inline void in(int a){split(root,a,x,y);root=merge(merge(x,new_node(a)),y);}
inline void del(int a){split(root,a,x,z);split(x,a-1,x,y);y=merge(ch[y][0],ch[y][1]);root=merge(merge(x,y),z);}
inline int pre(int a){split(root,a-1,x,y);int res=val[kth(x,size[x])];root=merge(x,y);return res;}
inline int nxt(int a){split(root,a,x,y);int res=val[kth(y,1)];root=merge(x,y);return res;}
}
using namespace std;
using namespace fhq;
int T,cur,p; int main()
{
srand(time(NULL));
T=read();
while(T--)
{
p=read(),cur=read();
if(p==1) fhq::in(cur);
else if(p==2) del(cur);
else if(p==3) printf("%d\n",fhq::rnk(cur));
else if(p==4) printf("%d\n",fhq::val[kth(root,cur)]);
else if(p==5) printf("%d\n",fhq::pre(cur));
else if(p==6) printf("%d\n",fhq::nxt(cur));
}
return 0;
}

哦,对了用fhq如果rp好的话还可以过掉NOIP2017列队。。。。可以尝试一下qwq

fhq treap——简单又好写的数据结构的更多相关文章

  1. 【POJ2761】【fhq treap】A Simple Problem with Integers

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  2. 【数据结构】FHQ Treap详解

    FHQ Treap是什么? FHQ Treap,又名无旋Treap,是一种不需要旋转的平衡树,是范浩强基于Treap发明的.FHQ Treap具有代码短,易理解,速度快的优点.(当然跟红黑树比一下就是 ...

  3. FHQ Treap小结(神级数据结构!)

    首先说一下, 这个东西可以搞一切bst,treap,splay所能搞的东西 pre 今天心血来潮, 想搞一搞平衡树, 先百度了一下平衡树,发现正宗的平衡树写法应该是在二叉查找树的基础上加什么左左左右右 ...

  4. 【数据结构】平衡树splay和fhq—treap

    1.BST二叉搜索树 顾名思义,它是一棵二叉树. 它满足一个性质:每一个节点的权值大于它的左儿子,小于它的右儿子. 当然不只上面那两种树的结构. 那么根据性质,可以得到该节点左子树里的所有值都比它小, ...

  5. 在平衡树的海洋中畅游(四)——FHQ Treap

    Preface 关于那些比较基础的平衡树我想我之前已经介绍的已经挺多了. 但是像Treap,Splay这样的旋转平衡树码亮太大,而像替罪羊树这样的重量平衡树却没有什么实际意义. 然而类似于SBT,AV ...

  6. BZOJ3159: 决战(FHQ Treap)

    传送门: 解题思路: 算是补坑了,这题除了Invert以外就可以树剖线段树解决了. 考虑Invert操作,延续先前树链剖分的做法,考虑先前算法的瓶颈. 最暴力的方法是暴力交换权值,然而这种方法忽略了当 ...

  7. 可持久化treap(FHQ treap)

    FHQ treap 的整理 treap = tree + heap,即同时满足二叉搜索树和堆的性质. 为了使树尽可能的保证两边的大小平衡,所以有一个key值,使他满足堆得性质,来维护树的平衡,key值 ...

  8. 并不对劲的fhq treap

    听说很对劲的太刀流不止会splay一种平衡树,并不对劲的片手流为了反驳他,并与之针锋相对,决定学学高端操作. 很对劲的太刀流-> 据说splay常数极大,但是由于只知道splay一种平衡树能对序 ...

  9. FHQ treap学习(复习)笔记

    .....好吧....最后一篇学习笔记的flag它倒了..... 好吧,这篇笔记也鸽了好久好久了... 比赛前刷模板,才想着还是补个坑吧... FHQ,这个神仙(范浩强大佬),发明了这个神仙的数据结构 ...

随机推荐

  1. LVM 逻辑卷管理

    简介: LVM ( Logical Volume Manager ) 逻辑卷管理 一.创建 LV 1.首先在你的虚拟机上添加一块新的硬盘用来做实验. 2.安装 lvm : yum -y install ...

  2. Notepad++ 多行一起编辑

      快捷方法: 鼠标:alt+滑鼠左鍵拖拉選取.鍵盤:alt+shift+方向鍵.

  3. APP微信登录---第三方登录

    (一)引入maven配置 <dependency> <groupId>com.github.liyiorg</groupId> <artifactId> ...

  4. Linux实战教学笔记27:Nginx详细讲解

    前言:nginx的特点 本节主要对Nginx Web服务软件进行介绍,涉及Nginx的基础,特性,配置部署,优化,以及企业中的日常运维管理和应用.作为HTTP服务软件的后起之秀,Nginx与它的老大哥 ...

  5. mysql的my.ini配置文件

    第一步,我们找到mysql安装文件下面的my.ini文件,打开可以看到第一句: # MySQL Server Instance Configuration File Mysql服务实例配置文件 好,咱 ...

  6. 【总结整理】AI产品经理大会2017(转载)

    从企业大数据到企业 AI | 易观智慧院院长 李智 1.AI 不是目的,而是要了解 AI 是什么,真正意义上的强人工智能在前沿领域尚未取得突破,暂时只能在影视文学作品中去思考人机关系.机器人三定律在未 ...

  7. 优化mysql slave的同步速度

    测试环境:Red Hat Enterprise Linux Server release 6.3 (Santiago)Server version: 5.6.22-log MySQL Communit ...

  8. Webdings和Wingdings字符码对应表

    刚才研究动网论坛代码,发现一个页面提示标记 i 感觉很神奇,看了半天才明白原来是一种叫“Webdings”的字体,其实很简单,只需要<font face='webdings' size=&quo ...

  9. C#中不同格式数据校验的正则表达式

    网上经常看到用正则表达式校验数据的文章,有的虽然总结得很全,但是大多数都没有经过严格验证,错误较多. 本文包含三十余条不同格式数据校验的C#正则表达式,一般均附有说明,且在Visual Studio里 ...

  10. Spring.net 在aps.net Web的配置复习

    1.引入程序集Spring.Core,CommonLogging,Spring.Web 2.Web.Config的配置 <?xml version="1.0" encodin ...