【洛谷P3369】 (模板)普通平衡树
https://www.luogu.org/problemnew/show/P3369
Splay模板
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define MAXN 100010 5 int n,sons[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],value[MAXN],root,Size; 6 inline int read(){ //快读 7 int x=0,ff=1; char c=getchar(); 8 while(c<'0'||c>'9') { if(c=='-') ff=-1; c=getchar(); } 9 while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } 10 return x*ff; 11 } 12 inline void clear(int x){ //清除节点x 13 f[x]=sons[x][0]=sons[x][1]=size[x]=cnt[x]=value[x]=0; 14 } 15 inline int get_w(int p){ 16 return sons[f[p]][1]==p; 17 } 18 inline void update(int p){ 19 if(p){ 20 size[p]=cnt[p]; 21 if(sons[p][0]) size[p]+=size[sons[p][0]]; 22 if(sons[p][1]) size[p]+=size[sons[p][1]]; 23 } 24 } 25 inline void rotate(int x){ //旋转节点x 26 int fa=f[x],gfa=f[f[x]],ws=get_w(x); 27 sons[fa][ws]=sons[x][ws^1]; //father与son 28 f[sons[fa][ws]]=fa; 29 f[fa]=x; //father与x 30 sons[x][ws^1]=fa; 31 f[x]=gfa; //x与grandfather 32 if(gfa) sons[gfa][sons[gfa][1]==fa]=x; 33 update(x); 34 update(fa); 35 } 36 inline void Splay(int x){ //将x旋到root 37 for(int fa;fa=f[x];rotate(x)) 38 if(f[fa]) 39 rotate(get_w(x)==get_w(fa)?fa:x); //若x,father,grandfather三个节点呈一条直线,就旋中间的节点 40 root=x; 41 } 42 void insert(int x){ //插入节点 43 if(!root){ //如果树为空 44 Size++; 45 f[Size]=sons[Size][0]=sons[Size][1]=0; 46 size[Size]=cnt[Size]=1; 47 value[Size]=x; 48 root=Size; 49 return; 50 } 51 int now=root,fa=0; 52 while(1){ 53 if(value[now]==x){ //如果已有的节点值=x 54 cnt[now]++; //该节点数量+1 55 update(now); 56 update(fa); 57 Splay(now); //旋到root,维护平衡树 58 return; 59 } 60 fa=now; 61 now=sons[now][x>value[now]]; 62 if(!now){ 如果旋到叶子节点,新开一个点 63 Size++; 64 sons[Size][0]=sons[Size][1]=0; 65 f[Size]=fa; 66 size[Size]=cnt[Size]=1; 67 value[Size]=x; 68 sons[fa][value[fa]<x]=Size; 69 update(fa); 70 Splay(Size); 71 return; 72 } 73 } 74 } 75 int find_num(int x){ //找大小顺序为x的节点的值 76 int now=root; 77 while(1){ 78 if(sons[now][0]&&x<=size[sons[now][0]]) now=sons[now][0]; //左子树大小>x,则向左子树查询 79 else{ 80 int temp=(sons[now][0]?size[sons[now][0]]:0)+cnt[now]; 81 if(x<=temp) return value[now]; //x包含在cnt[now]中 82 x-=temp; 83 now=sons[now][1]; 84 } 85 } 86 } 87 int find_rank(int x){ //查询值为x的点的大小编号 88 int now=root,ans=0; 89 while(1){ 90 if(x<value[now]) now=sons[now][0]; 91 else{ 92 ans+=sons[now][0]?size[sons[now][0]]:0; 93 if(x==value[now]){ 94 Splay(now); 95 return ans+1; 96 } 97 ans+=cnt[now]; 98 now=sons[now][1]; 99 } 100 } 101 } 102 inline int find_pre(){ //root的前驱即为左子树中最靠右的点 103 int now=sons[root][0]; 104 while(sons[now][1]) now=sons[now][1]; 105 return now; 106 } 107 inline int find_suf(){ 108 int now=sons[root][1]; 109 while(sons[now][0]) now=sons[now][0]; 110 return now; 111 } 112 void delete_node(int x){ //删除节点x 113 find_rank(x); //将x旋上去 114 if(cnt[root]>1){ 115 cnt[root]--; 116 update(root); 117 return; 118 } 119 if(!sons[root][1]&&!sons[root][0]){ 120 clear(root); root=0; return; 121 } 122 if(!sons[root][1]){ 123 int last=root; 124 root=sons[root][0]; 125 f[root]=0; 126 clear(last); 127 return; 128 } 129 if(!sons[root][0]){ 130 int last=root; 131 root=sons[root][1]; 132 f[root]=0; 133 clear(last); 134 return; 135 } 136 int last=root,pre=find_pre(); //将前驱旋上去,此时x为pre的右儿子,直接删除即可(类似于链表) 137 Splay(pre); 138 sons[root][1]=sons[last][1]; 139 f[sons[last][1]]=root; 140 clear(last); 141 update(root); 142 } 143 int main() 144 { 145 n=read(); 146 int opt,x; 147 while(n--){ 148 opt=read(); x=read(); 149 switch(opt){ 150 case 1: insert(x); break; 151 case 2: delete_node(x); break; 152 case 3: printf("%d\n",find_rank(x)); break; 153 case 4: printf("%d\n",find_num(x)); break; 154 case 5: insert(x);printf("%d\n",value[find_pre()]);delete_node(x); break; 155 case 6: insert(x);printf("%d\n",value[find_suf()]);delete_node(x); break; 156 } 157 } 158 return 0; 159 }
转载于:https://www.cnblogs.com/yjkhhh/p/9206240.html
【洛谷P3369】 (模板)普通平衡树相关推荐
- 【洛谷P3369】普通平衡树(splay)
emmmmm直接丢代码了 #include<iostream> #include<cstdio> #include<cstring> #include<str ...
- 专题·树链剖分【including 洛谷·【模板】树链剖分
初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...
- 洛谷·【模板】点分树 | 震波【including 点分树
初见安-这里是传送门:洛谷P6329 [模板]点分树 | 震波 一.点分树 其实你会点分治的话,点分树就是把点分治时的重心提出来重新连城一棵树. 比如当前点是u,求出子树v的重心root后将root与 ...
- 洛谷P3369 【模板】普通平衡树(STL做法:vectormultiset)
problem solution1 - AC vector可以AC.lower_bound找第一个大于等于x的,upper_bound找第一个大于x的. #include<bits/stdc++ ...
- 洛谷P3369 普通平衡树
刚学平衡树,分别用了Splay和fhq-treap交了一遍. 这是Splay的板子,貌似比较短? Splay #include <iostream> #include <cstdio ...
- 洛谷.3919.[模板]可持久化数组(可持久化线段树/平衡树)
题目链接 //利用先前的根节点建树 想一下不难写. #include <cstdio> #include <cctype> //#define gc() getchar() # ...
- 洛谷.4897.[模板]最小割树(Dinic)
题目链接 最小割树模板.具体见:https://www.cnblogs.com/SovietPower/p/9734013.html. ISAP不知为啥T成0分了.. Dinic: //1566ms ...
- 强连通分量:洛谷P3387 模板:缩点
传送门 顾名思义,模板awa #include <cstdio> #include <cstring> #include <cmath> #include < ...
- 【后缀数组】洛谷P3809模板题
题目背景 这是一道模板题. 题目描述 读入一个长度为 n n n 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置. ...
最新文章
- 东北师范大学计算机科学与技术学科评估,东北的大学最强十校,工科是真强,2所211大学无缘前十...
- Servlet_urlpartten配置
- 四大步骤做好需求调研
- Facebook F8|闲鱼高级技术专家参会分享
- ITIL-IT运维管理-概述
- 软件项目经理应具备的素质和条件_项目经理应具备的素质和能力
- 10行java代码实现email代码表白感恩节必备~
- HashMap的put过程
- 定制婚礼小程序开发功能
- c语言中查重,体验CCleaner查重功能,快速找出电脑中的重复文件
- C++-FFmpeg-(5)-2-h264-概念与名词:宏块-I-P-B帧;参数设置:ABR、CQP、CBR、CRF;码流:SPS-PPS
- BackTrack3 硬盘安装教程
- 人工优化的B2B信息发布系统
- paypal支付 paypal网站付款标准版问题解决
- RK3399驱动开发 | 15 - RTC实时时钟芯片HYM8563S调试(基于linux5.4.32内核)
- 线性代数学习笔记——第五十四讲——非齐次方程组解的性质
- python中国地图代码 上色_如何让使用python绘制中国地图并给特定地区上色?
- GNU Make工具(二)Phony Targets 和 FORCE
- HAUT OJ 1508 zp与车费
- 流氓软件之会声会影[彻底卸载]
热门文章
- 老毛桃安装WIN7原版系统
- C++中用TinyXML对XML文件进行解析
- y53拆机视频教程_vivoY53L拆机图赏
- 从零开始刷Leetcode——数组(532.561)
- 在哪里定义_定义市场的关键字:找出它们在哪里使用,以便您可以抢占该市场...
- 高斯过程回归python_scikit-learn中的多输出高斯过程回归
- 如何确定电脑主板坏了_原阳县地暖漏水如何检测
- floodfill算法 java_OpenCV 3 floodFill(漫水填充)、图片的放大缩小 pyrUp、pyrDown、Resize JAVA OpenCV专题学习10...
- apktool 反编译 java_APK文件使用ApkTool解包反编译和重新打包及签名
- 动态取值_软件测试|动态测试技术