Splay
来源:互联网 发布:淘宝客服接待人特别少 编辑:程序博客网 时间:2024/04/26 19:46
Splay
Splay是一种平衡树。
既然是一棵平衡树,那么我们一定要想办法让它保持平衡。
解决办法就是旋转,分为zig,zag,zig-zig,zag-zag,zig-zag,zag-zig。
核心:Splay操作,通过进行非常多次的Splay操作来保证所有操作的均摊复杂度为O(logn)。(我不会证明)
详细讲解(转载):
http://blog.csdn.net/clove_unique/article/details/50630280
Q:为什么旋转的时候要向上考虑两层?
A:可以动手画图试试,然后就会发现不考虑两层会出问题。
Q:怎么考虑啊?
A:x和y同为各自父亲的左孩子或者右孩子时,进行zag-zag或者zig-zig,否则zag-zig或者zig-zag。
例题 Luogu 3369
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
解析
这就是模板啦
代码如下
#include<bits/stdc++.h>using namespace std;#define maxn 1000000#define INF 2147483647int n,fa[maxn],val[maxn],c[maxn][2],root,tot,siz[maxn],cnt[maxn];void Maintain(int x){ siz[x]=siz[c[x][0]]+siz[c[x][1]]+cnt[x];}void NewNode(int &x,int Fa,int key){ x=++tot; fa[x]=Fa; c[x][0]=c[x][1]=0; val[x]=key; siz[x]=cnt[x]=1;}void Rotate(int x,bool flag){ int y=fa[x]; c[y][!flag]=c[x][flag]; fa[c[x][flag]]=y; if(fa[y]){ c[fa[y]][c[fa[y]][1]==y]=x; } fa[x]=fa[y]; c[x][flag]=y; fa[y]=x; Maintain(y); Maintain(x);}void Splay(int x,int goal){ if(!x){ return; } int y; while((y=fa[x])!=goal){ if(fa[y]==goal){ Rotate(x,c[y][0]==x); } else{ if((c[y][0]==x)==(c[fa[y]][0]==y)){ Rotate(y,c[fa[y]][0]==y); } else{ Rotate(x,c[y][0]==x); y=fa[x]; } Rotate(x,c[y][0]==x); } } Maintain(x); if(!goal){ root=x; }}int Find(int key,int x=root){ while(c[x][val[x]<key]){ if(val[x]==key){ return x; } x=c[x][val[x]<key]; } return x;}void Insert(int key){ if(!root){ NewNode(root,0,key); return; } int x=Find(key); if(val[x]==key){ ++cnt[x]; Splay(x,0); return; } NewNode(c[x][val[x]<key],x,key); Splay(c[x][val[x]<key],0);}int Findmax(int x=root){ while(c[x][1]){ x=c[x][1]; } return x;}int Findmin(int x=root){ while(c[x][0]){ x=c[x][0]; } return x;}void Delete(int key){ int x=Find(key); Splay(x,0); if(val[x]==key){ --cnt[x]; if(!cnt[x]){ if(!c[x][0]&&!c[x][1]){ root=0; } else if(!c[x][0]||!c[x][1]){ fa[c[x][c[x][0]==0]]=0; root=c[x][c[x][0]==0]; } else{ int y=Findmax(c[x][0]); Splay(y,root); c[y][1]=c[root][1]; fa[c[root][1]]=y; root=y; fa[root]=0; Maintain(root); } } else{ Maintain(x); } }}int Rank(int key){ int x=Find(key); Splay(x,0); return siz[c[x][0]]+1;}int Kth(int K,int x=root){ while(1){ int Siz0=siz[c[x][0]]; if(K<=Siz0){ x=c[x][0]; } else if(K<=Siz0+cnt[x]){ return val[x]; } else{ K-=(Siz0+cnt[x]); x=c[x][1]; } }}int GetPre(int key){ int x=Find(key); if(val[x]==key){ Splay(x,0); return val[Findmax(c[x][0])]; } while(val[x]>key&&fa[x]){ x=fa[x]; } return val[x];}int GetNex(int key){ int x=Find(key); if(val[x]==key){ Splay(x,0); return val[Findmin(c[x][1])]; } while(val[x]<key&&fa[x]){ x=fa[x]; } return val[x];}int main(){ int op, x; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&op,&x); if(op==1){ Insert(x); } else if(op==2){ Delete(x); } else if(op==3){ printf("%d\n",Rank(x)); } else if(op==4){ printf("%d\n",Kth(x)); } else if(op==5){ printf("%d\n",GetPre(x)); } else{ printf("%d\n",GetNex(x)); } } return 0;}
另一道题 洛谷 3391
传送门:http://blog.csdn.net/vanillayi/article/details/78715357
阅读全文
0 0
- SPLAY
- splay
- splay
- splay
- Splay
- Splay
- splay
- splay
- splay
- splay
- Splay
- splay
- Splay
- splay
- Splay
- Splay
- splay
- Splay大功告成
- openstack安装Apache HTTP后却无法启动它
- Openjudge 1.13 50树根
- Matplotlib可视化库的使用
- 学习记录1
- 拼接接口
- Splay
- spring boot工程实践入门
- Jzoj3486 道路改建
- 自定义圆形进度条
- java 用一行代码 找到 一维数组 最大值最小值 的下标
- jvm探秘二:对象的创建
- hdu4602 Partition 快速幂
- jdk双版本切换
- mac上phpinfo()可以看到swoole模块但是提示swoole_server(class no found)