FHQ

    xiaoxiao2023-09-26  135

    文章目录

    前言基本操作合并操作分离操作【扩展】分离操作 应用操作插入其他操作 结束语关于本文作者鸣谢

    前言

    去年底我学了Treap,Splay和替罪羊。综合起来看,我个人认为还是FHQ_Treap比较实用。重点是比较好写而且写起来不容易挂。对于我这种蒟蒻,在写Treap和Splay时是常常爆炸的。所以FHQ_Treap成了蒟蒻我写平衡树的唯一救命稻草。

    记得当时我没怎么学FHQ_Treap,今天我就来复习一下这个神奇的数据结构。

    基本操作

    这个玩意儿基本操作很少,但是能完成所有的平衡树操作

    合并操作

    int merge(int x, int y) { if(!x||!y) return x+y; if(rd[x]<rd[y]) { ch[x][1]=merge(ch[x][1], y); up_node(x); return x; } else { ch[x][0]=merge(x, ch[y][0]); up_node(y); return y; } }

    分离操作

    void split(int now, int p, int &x, int &y) {//now树中,以k为分割点,分为x,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]); } up_node(now); } }

    【扩展】分离操作

    摘自这里,侵删

    应用操作

    插入

    int insert(int &root, int x) {//原树root,插入x int a, b; int v=val[x]; split(root, v, a, b); root=marge(marge(a, x), b); }

    其他操作

    void insert(int v) { int x,y; split(rt,x,y,v-1); merge(x,x,newnode(v)); merge(rt,x,y); } void del(int v) { int x,y,z; split(rt,x,y,v); split(x,x,z,v-1); merge(z,ls[z],rs[z]); merge(x,x,z); merge(rt,x,y); } void rk(int v) { int x,y; split(rt,x,y,v-1); printf("%d\n",sz[x]+1); merge(rt,x,y); } int kth(int k) { int x=rt; while(1) { if(k==sz[ls[x]]+1)return val[x]; if(k<=sz[ls[x]])x=ls[x]; else k-=sz[ls[x]]+1,x=rs[x]; } } void pre(int v) { int x,y; split(rt,x,y,v-1); printf("%d\n",sz[x]?kth(x,sz[x]):-inf); merge(rt,x,y); } void suf(int v) { int x,y; split(rt,x,y,v); printf("%d\n",sz[y]?kth(y,1):inf); merge(rt,x,y); }

    这些都不是很难,不需要注释

    结束语

    如果你不理解,最好是自己打一遍代码或者是做一个有关FHQ_Treap的梦,就什么都懂了。

    关于本文

    作者

    海洋,初一大蒟蒻

    鸣谢

    巨学博客

    最新回复(0)