当前位置: 首页 > news >正文

fhq-treap学习笔记

本文内容粗略,不适合新手阅读
但如果你已经进来了,推荐你到这里学习
当然是写给我复习用

fhq-treap通过分裂和合并连个操作,以临界值分离二叉搜索树

由于在合并时引进可了随机数,使其平衡性得到保障

结构体

struct node{int ls,rs,val,p,s;//分别为左儿子,右儿子,该节点存的值,随机数(用于合并),以该节点为根的子树的大小
};

分离

void split(int u,int x,int& l,int& r){//u当前节点,x临界值,l在值域为1到x之间的树接下来需要添加节点的位置,r与l同理,值域在x+1到m之间if(u==0){//如果u节点时不存在的,这里不需要添加,l和r指向0,以该节点为根的子树大小l=r=0;return;}if(t[u].val<=x){//当前节点的值比x小,因为以其左节点为根的子树的值均小于该节点的值,所以将左子树和当前节点给l,右子树继续分离l=u;split(t[u].rs,x,t[u].rs,r);}else{//与上同理r=u;split(t[u].ls,x,l,t[u].ls);}push_up(u);//更新节点大小
}

合并

合并时,并不能确定哪个点作为根,如果只选左或只选右或诸如此类有规律性的选法,很有可能使平衡树退化

所以引入随机数,随机数p值较大的优先作为根节点

//调用merge的条件:u点的val小于等于v点的val
int merge(int u,int v){//返回merge后的根节点if(!u||!v) return u|v;if(t[u].p>t[v].p){//u为根节点t[u].rs=merge(t[u].rs,v);//注意顺序push_up(u);return u;}else{//v为根节点t[v].ls=merge(u,t[v].ls);//注意顺序push_up(v);return v;}
}

模板

然后就可以通过merge和split进行各种操作了

过程中维护一个根节点即可

放个我自己写的模板

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
void read(int& x){char c;bool f=0;while((c=getchar())<48) f|=(c==45);x=c-48;while((c=getchar())>47) x=x*10+c-48;x=(f ? -x : x);return;
}
mt19937 rd(time(NULL));
struct node{int ls,rs,val,p,s;
};
int node_cnt=0,rt;
node t[maxn];
int new_node(int x){++node_cnt;t[node_cnt]=(node){0,0,x,(int)rd(),1};return node_cnt;
}
void push_up(int u){t[u].s=t[t[u].ls].s+t[t[u].rs].s+1;
}
void split(int u,int x,int& l,int& r){if(u==0){l=r=0;return;}if(t[u].val<=x){l=u;split(t[u].rs,x,t[u].rs,r);}else{r=u;split(t[u].ls,x,l,t[u].ls);}push_up(u);
}
int merge(int u,int v){if(!u||!v) return u|v;if(t[u].p>t[v].p){t[u].rs=merge(t[u].rs,v);push_up(u);return u;}else{t[v].ls=merge(u,t[v].ls);push_up(v);return v;}
}
void insert(int x){int u,v;split(rt,x,u,v);int p=new_node(x);rt=merge(merge(u,p),v);
}
void remove(int x){int u,v,w;split(rt,x,u,v);split(u,x-1,u,w);w=merge(t[w].ls,t[w].rs);rt=merge(merge(u,w),v);
}
int rnk(int x){int u,v;split(rt,x-1,u,v);int ans=t[u].s+1;rt=merge(u,v);return ans;
}
int kth(int x,int u=rt){int i=t[t[u].ls].s+1;if(i==x) return t[u].val;else if(x<i) return kth(x,t[u].ls);else return kth(x-i,t[u].rs);
}
int pre(int x){int u,v;split(rt,x-1,u,v);int ans=kth(t[u].s,u);rt=merge(u,v);return ans;
}
int nxt(int x){int u,v;split(rt,x,u,v);int ans=kth(1,v);rt=merge(u,v);return ans;
}
int q;
int main(){//freopen(".in","r",stdin);//freopen(".out","w",stdout);read(q);int op,x;while(q--){read(op),read(x);if(op==1) insert(x);else if(op==2) remove(x);else if(op==3) printf("%d\n",rnk(x));else if(op==4) printf("%d\n",kth(x));else if(op==5) printf("%d\n",pre(x));else printf("%d\n",nxt(x));}return 0;
}
//^o^
http://www.vanclimg.com/news/418.html

相关文章:

  • 7/28
  • Bruce Momjian 深圳 meetup 回顾
  • 贪心
  • sqlite3 本地数据库可视化工具
  • [题解] P5743 【深基7.习8】猴子吃桃
  • gds 格式文档
  • 微服务学习-02-微服务技术栈整理
  • JUC线程池: ScheduledThreadPoolExecutor详解
  • [题解] P5735 【深基7.例1】距离函数
  • uv命令怎么安装并且让gitlab-runner用户可以执行
  • NRF54L15 TAMPC — Tamper controller 作用介绍
  • 线上故障的排查清单,运维小哥拿走不谢!
  • NRF54L15 AAR作用介绍
  • NRF54L15 CCM功能
  • 恭贺开源之夏 2025 IvorySQL 项目中选学生
  • 自用学习笔记:机器学习入门 速览【第三章】
  • 浅谈MCU的启动
  • KMU — Key management unit 作用
  • NRF54L15 GRTC 优点;
  • MS14-019漏洞修复:通过.cmd或.bat文件实现二进制劫持的解决方案
  • 浅谈北京市海淀区七年级下册期末数学试卷T16第二小问
  • 利用Amazon Bedrock生成AI增强设备维护建议
  • SAP为何将S/4HANA更名为SAP Cloud ERP?
  • NRF54L15 关机状态功耗;
  • JUC学习-22-浅谈线程池参数原理
  • C/C++环境搭建
  • 记录Mysql主从
  • To do list
  • 我的博客
  • 基于帧差法与Vibe算法的matlab前景提取