Luogu P3369 【模板】普通平衡树


啊 splay啊

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>//左儿子一定比我小 右儿子一定比我大
/*        * <----0| * <----rt /   \*    */ \  / \*  * *   *   这是一棵树
*/  struct nod1{int ch[2],c,fa,size,cnt;}tr[110010];
//ch[0]是左儿子编号 ch[1]是右儿子比那好
//c是节点数值 fa是节点爸爸 size是以节点为根子树大小
//cnt是和节点数值一样的数的个数
int n,rt,tot;
//n是操作数 rt是根 tot是整个数的节点个数,添加新节点时用到 void update(int x)//更新维护 此处x是编号
{tr[x].size=tr[tr[x].ch[0]].size+tr[x].cnt+tr[tr[x].ch[1]].size;//x子树大小=x左子树+x右子树+x节点相同数个数 return ;
}//okint findip(int x)//找x数值的节点编号 此处x是数值
{int now=rt;//从根开始找 while(x!=tr[now].c){if(x<tr[now].c)//比当前点数值小 {if(tr[now].ch[0]==0)break;//没有,只好跳出循环 返回当前这个now 是与x最贴切的节点 now=tr[now].ch[0];//走左边 }else{if(tr[now].ch[1]==0)break;now=tr[now].ch[1];//走右边 }}return now;
}void add(int c,int x)//添加新节点 此处c是数值,x是新节点爸爸的编号
{tot++;tr[tot].c=c;tr[tot].cnt=1;tr[tot].size=1;tr[tot].fa=x;tr[tot].ch[0]=tr[tot].ch[1]=0;if(c<tr[x].c)tr[x].ch[0]=tot;else tr[x].ch[1]=tot;//判断新节点是爸爸的左儿子还是右儿子 return ;
}void rotate(int x,int w)//单旋 此处x是编号 w是儿子标记 w等于1意味着我是我爸的左儿子,否则为我爸的右儿子
{int f=tr[x].fa,ff=tr[f].fa;tr[f].ch[1-w]=tr[x].ch[w];//这里的ch[0]是左儿子,ch[1]是右儿子//如果我是我爸的右儿子,那么说明我的整棵子树都比他大,所以我的左儿子给我爸当右儿子//如果我是我爸的左儿子,那么说明我的整棵子树都比他小,所以我的右儿子给我爸当左儿子if(tr[x].ch[w]!=0)tr[tr[x].ch[w]].fa=f; if(tr[ff].ch[0]==f)tr[ff].ch[0]=x;//爷爷>爸爸 else tr[ff].ch[1]=x;//爸爸是爷爷什么儿子 我旋转后就给爷爷当什么儿子 tr[x].fa=ff;tr[f].fa=x;tr[x].ch[w]=f;update(f);//更新底层 update(x);//更新当前层
}void splay(int x,int goal)//把x旋到目标节点下面
{while(tr[x].fa!=goal){int f=tr[x].fa,ff=tr[f].fa;if(ff==goal)//爷爷就是目标{//旋一次就行 if(x==tr[f].ch[0])//我<我爸 rotate(x,1);else rotate(x,0);} else{if(tr[ff].ch[0]==f)//爷爷>我爸 {if(tr[f].ch[0]==x)//我爸>我 {//我与我爸共线 则双旋rotate(f,1);//我爸是我爷爷左儿子 rotate(x,1);//我是我爸左儿子 }else{//我爸<我 rotate(x,0);//我是我爸右儿子 rotate(x,1);//现在我是我爷爷左儿子}} else//爷爷<我爸 { if(tr[f].ch[0]==x){rotate(x,1);//我是我爸左儿子 rotate(x,0);//现在我是我爷爷右儿子 }else{//我与我爸共线 则双旋rotate(f,0);//我爸是我爷爷右儿子 rotate(x,0);//我是我爸右儿子 }}} }if(goal==0)rt=x;
}void insert(int x)//插入一个数 此处x是数值
{if(rt==0){//第一个节点 先让你当0儿子 add(x,0);rt=tot;return ;}int ip=findip(x);//找出x数值的节点编号或是最贴近的节点 if(tr[ip].c==x){//之前插入过这个数值 tr[ip].cnt++;update(ip);splay(ip,0);}else{add(x,ip);//新点 update(ip);splay(tot,0);}
}void del(int x)//删除一个数 此处x是数值
{int ip=findip(x);//拿它编号 splay(ip,0);//让它当根 方便操作 if(tr[ip].c!=x)return ;//之前没有插入过这个数值 if(tr[ip].cnt>1){//不止一个这个数值 tr[ip].cnt--;update(ip);}else if(tr[ip].ch[0]==0&&tr[ip].ch[1]==0)//已经将这个点旋到根了 如果没有左右儿子 说明整棵树只有一个点 rt=0,tot=0;else if(tr[ip].ch[0]!=0&&tr[ip].ch[1]==0)//只有一个儿子就让他继承 rt=tr[ip].ch[0],tr[tr[ip].ch[0]].fa=0;else if(tr[ip].ch[1]!=0&&tr[ip].ch[0]==0)//只有一个儿子就让他继承 rt=tr[ip].ch[1],tr[tr[ip].ch[1]].fa=0;else{int p=tr[ip].ch[0];while(tr[p].ch[1]!=0)p=tr[p].ch[1];//找前驱来 splay(p,ip);//旋到我这里来,因为前驱是小于我中最大的 它此时没有右儿子 rt=p;tr[p].fa=0;tr[tr[ip].ch[1]].fa=p;//直接把右儿子给它 tr[p].ch[1]=tr[ip].ch[1];update(p);}
}int rank(int x)//此处x是数值 找出x的排名
{int ip=findip(x);splay(ip,0);//把我旋成根 方便处理 return tr[tr[ip].ch[0]].size+1;//我是根 所以左子树全小于我 +1就是我排名
}int kth(int x)//找排名是x的数值
{int now=rt;while(1){if(x<=tr[tr[now].ch[0]].size)//如果我小于左边的个数 去左边找 now=tr[now].ch[0];else if(tr[tr[now].ch[0]].size+tr[now].cnt<x){//如果比左+当前自己还大 去右边 x=x-tr[tr[now].ch[0]].size-tr[now].cnt;now=tr[now].ch[1];} else break;//等于当前 }return tr[now].c;
}int last(int x)//找前驱 此处x是数值
{int ip=findip(x);splay(ip,0);if(x<=tr[ip].c&&tr[ip].ch[0]!=0){ip=tr[ip].ch[0];while(tr[ip].ch[1]!=0)ip=tr[ip].ch[1];} //比我小最大的:左子树最右的 if(x<=tr[ip].c)return 0;return tr[ip].c;
}int next(int x)//找后继 此处x是数值
{int ip=findip(x);splay(ip,0);if(x>=tr[ip].c&&tr[ip].ch[1]!=0){ip=tr[ip].ch[1];while(tr[ip].ch[0]!=0)ip=tr[ip].ch[0]; } //比我大最小的:右子树最左边if(x>=tr[ip].c)return 0;return tr[ip].c;
}int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){int h,x;scanf("%d %d",&h,&x);if(h==1)insert(x);else if(h==2)del(x);else if(h==3)printf("%d\n",rank(x));else if(h==4)printf("%d\n",kth(x));else if(h==5)printf("%d\n",last(x));else if(h==6)printf("%d\n",next(x));}
}

看了好多博客 要昏了

Luogu P3369 【模板】普通平衡树相关推荐

  1. [学习笔记] 伸展树splay详解+全套模板+例题[Luogu P3369 【模板】普通平衡树]

    文章目录 引入概念 全套模板 变量声明 update ==rotate旋转== splay操作 insert插入 delete删除 查找x的位置 查找第k大 前驱/后继 极小值-inf和极大值inf的 ...

  2. fhq treap ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

    二次联通门 : LibreOJ #104. 普通平衡树 #include <cstdio> #include <iostream> #include <algorithm ...

  3. 【洛谷P3369】 (模板)普通平衡树

    https://www.luogu.org/problemnew/show/P3369 Splay模板 1 #include<iostream> 2 #include<cstdio& ...

  4. Luogu P2717 寒假作业(平衡树)

    P2717 寒假作业 题意 题目背景 \(zzs\)和\(zzy\)正在被寒假作业折磨,然而他们有答案可以抄啊. 题目描述 他们共有\(n\)项寒假作业.\(zzy\)给每项寒假作业都定义了一个疲劳值 ...

  5. 【洛谷P3369】普通平衡树(splay)

    emmmmm直接丢代码了 #include<iostream> #include<cstdio> #include<cstring> #include<str ...

  6. [Luogu] P3376 模板-网络流-最大流

    题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...

  7. luogu P3379 【模板】最近公共祖先(LCA)

    lca最近公共祖先,是指两个点最近的祖先节点:求lca我知道的有三种倍增, st表,tarjan,我要介绍的是倍增,我才不会告诉你我只会这一个. 话说我学lca可真的路途曲折,在qbxt,lcy da ...

  8. C++ __gnu_pbds(平板电视)超详细教程(C++内置的平衡树,字典树,hash)

    整理的算法模板合集: ACM模板 目录 一.平衡树 例题:luogu P3369 [模板]普通平衡树 1. `rb_tree_tag`版 2. `splay_tree_tag`版 功能不够?自己添加! ...

  9. 平衡树【Splay树】学习小记

    简介 平衡树,顾名思义,平衡的搜索二叉树. 常见的平衡树都能将树的深度保持在 lg ⁡ n \lg_n lgn​ 的级别内,防止退化成链. 一些平衡树可以通过旋转.分裂.合并等操作完成更加高级的.二叉 ...

  10. 平衡树学习笔记之 fhq Treap

    平衡树学习笔记 1:fhq Treap(非旋 Treap) 正文开始前首先 %%% fhq 大佬. 众所周知,平衡树是一种 非常猥琐 码量堪忧的数据结构. 他的祖先是一种叫做二叉搜索树 ( B S T ...

最新文章

  1. python if语句多个条件-python – if / elif语句的多个条件
  2. Coursera课程Python for everyone:chapter4
  3. C++指针数组、数组指针、数组名及二维数组技巧汇总
  4. Pytorch笔记:维度dim的定义及其理解使用
  5. 一份来自清华的数据分析笔记,请查收!
  6. PSpice应用 软件安装和B-1
  7. 基于FPGA(cyclone IV)的NOR FLASH的应用
  8. 手机android怎么结束后台,如何关闭手机后台运行程序
  9. python图像纹理提取_图像处理7 LBP纹理特征提取
  10. 手机版制作H5页面免费工具大集合
  11. 商业银行的起源与经营模式-分业经营与混业经营
  12. VERICUT9.0三四五多轴仿真加工视频教程
  13. 音视频开发之旅(六) -----Android集成webrtc降噪和增益模块, ns_core函数简析
  14. native vlan设置错误导致无法访问的问题排查过程
  15. php抓ik123音乐,IK123下载工具收藏下载网络DJ音乐教程
  16. php图片生成加密pdf文件,php生成PDF格式文件并且加密
  17. .\output\stm32f103.axf: Error: L6218E: Undefined symbol __aeabi_assert (referred from mqtt.o).
  18. CVPR 2022 | 数据堂亮相计算机视觉领域盛会
  19. Failed to start LSB: Bring up/down networking
  20. honor 9x android 10,【荣耀9X升级EMUI10指南】终于等到你,9XPro+EMUI10再战三年!

热门文章

  1. 计算机系统最重要的是什么,操作系统最重要的两个作用是什么
  2. 我在蚂蚁金服做后端:那些坚持在一个岗位做八年的人,后来怎么样了?...
  3. grub通过img文件启动linux,通过grub4dos引导本地linux系统
  4. C语言-投票选举问题
  5. 网页颜色搭配表及颜色搭配技巧
  6. 什么是DNS服务器?
  7. H3CNE综合小实验
  8. DISC社交风格测试题--老虎 孔雀 考拉 猫头鹰
  9. 如何显示隐藏文件和文件扩展名
  10. 像电影里的黑客高手一样敲代码攻击入侵网站!装逼神器 !