【bzoj3224】普通平衡树(splay板子)
来源:互联网 发布:嵌入式软件开发技术 编辑:程序博客网 时间:2024/05/20 02:55
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
101 1064654 11 3177211 4609291 6449851 841851 898516 819681 4927375 493598
Sample Output
10646584185492737
I think
代码参考(基本是二者的混合体qvq):
史上最详尽的平衡树(splay)讲解与模板
Splay伸展树学习笔记
splay板子……
稍微一提的是求前驱(后继),相当于新插入一个节点(顺便就旋至根节点啦),找根节点的左(右)子树中val最大(小)的节点,找到之后再删去该新建节点。
对于删除节点,可利用find()函数(查询x数的排名)将目标点旋至根节点,通过判断其子树情况分类处理。这里具体写写两颗子树均不为空的删除操作。
找到被删除节点x的左子树中val最大的节点y,并将其旋至x左子树根,由于y的val值大于左子树中任意其他节点,因此y一定没有右子树。那么将原x的右子树接至y的右子树,并将相关信息修改好就ok啦。
Code
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int sm = 1e5+5;int u,n,m,sz,opt,rt;int f[sm],c[sm],cnt[sm],size[sm],ch[sm][2];char a;void read(int &x) { x=0;a=getchar();u=1; while(a>'9'||a<'0') { if(a=='-')u=-1;a=getchar(); } while(a>='0'&&a<='9')x=x*10+a-'0',a=getchar(); x*=u;}bool son(int p,int fa) {//判断p是fa的左子树还是右子树 return ch[fa][1]==p;}void clear(int p) {//删除点p的各项信息 f[p]=ch[p][0]=ch[p][1]=size[p]=cnt[p]=c[p]=0;}void newnode(int val,int fa) {//给fa创建一个新的子节点,记得在调用之后更新fa的ch ++sz;f[sz]=fa; ch[sz][0]=ch[sz][1]=0; size[sz]=1;cnt[sz]=1;c[sz]=val;}void update(int x) {//更新以x为根的子树大小 if(x) { size[x]=cnt[x]; if(ch[x][0])size[x]+=size[ch[x][0]]; if(ch[x][1])size[x]+=size[ch[x][1]]; }}void rotate(int x) {//把x旋至其父亲 int fa=f[x],gf=f[fa]; int a=son(x,fa),b=!a; ch[fa][a]=ch[x][b]; if(ch[x][b])f[ch[x][b]]=fa; ch[x][b]=fa,f[fa]=x; f[x]=gf; if(gf)ch[gf][son(fa,gf)]=x; else rt=x; update(fa);update(x);}void splay(int x,int p) {//将x旋至p的子节点 while(f[x]!=p) { int fa=f[x],gf=f[fa]; if(p==gf)rotate(x); else { if(son(x,fa)^son(fa,gf)) rotate(x),rotate(x); else rotate(fa),rotate(x); } }}void insert(int val) {//插入一个值为val的新节点 if(!rt){ newnode(val,0);rt=sz;return;} int now=rt,fa=f[now]; while(now) { if(c[now]==val) { splay(now,0);cnt[now]++;return;//记得将节点旋至根 } fa=now; now=ch[fa][val>c[fa]]; if(!now) { newnode(val,fa); ch[fa][val>c[fa]]=sz; update(fa);splay(sz,0);return;//记得将节点旋至根 } }}int find(int val) {//查询值为val的点的排名 int ans=0,now=rt; while(now) { if(val<c[now]) now=ch[now][0]; else { ans+=(ch[now][0]?size[ch[now][0]]:0); if(val==c[now]) { splay(now,0);return ans+1;} ans+=cnt[now]; now=ch[now][val>c[now]]; } }}int findx(int p) {//查询排名为p的数 int ans=0,now=rt; while(now) { if(ch[now][0]&&p<=size[ch[now][0]]) now=ch[now][0]; else { int tmp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now]; if(p<=tmp)return c[now]; p-=tmp; now=ch[now][1]; } }}int pre() {//求前驱 int now=ch[rt][0]; while(ch[now][1]) now=ch[now][1]; return now;}int nxt() {//求后继 int now=ch[rt][1]; while(ch[now][0]) now=ch[now][0]; return now;}void del(int val) {//删除值为val的点 find(val); if(cnt[rt]>1){--cnt[rt];return;} if(!ch[rt][0]&&!ch[rt][1]){ clear(rt);return;} else if(!ch[rt][0]) { int t=rt;rt=ch[rt][1];f[rt]=0;clear(t);return; } else if(!ch[rt][1]) { int t=rt;rt=ch[rt][0];f[rt]=0;clear(t);return; } int l=pre(); splay(l,rt); f[ch[rt][1]]=l; ch[l][1]=ch[rt][1]; f[l]=0;clear(rt); rt=l;update(rt);}int main() { read(n); while(n--) { read(opt);read(m); if(opt==1)insert(m); else if(opt==2)del(m); else if(opt==3)printf("%d\n",find(m)); else if(opt==4)printf("%d\n",findx(m)); else { insert(m); if(opt==5)printf("%d\n",c[pre()]); else printf("%d\n",c[nxt()]); del(m); } } return 0;}
阅读全文
0 0
- 【bzoj3224】普通平衡树(splay板子)
- bzoj3224普通平衡树 Splay
- [BZOJ3224] 普通平衡树 - splay
- BZOJ3224 普通平衡树(splay)
- [BZOJ3224][SPLAY]普通平衡树
- [BZOJ3224]普通平衡树 SPlay
- bzoj3224普通平衡树splay
- BZOJ3224 普通平衡树 Splay + 替罪羊树
- BZOJ3224普通平衡树splay,SBT代码
- 【BZOJ3224】 【CODEVS4543】 普通平衡树 splay
- bzoj3224 普通平衡树【splay版】
- 【bzoj3224】【Tyvj1728】【普通平衡树】【splay】
- bzoj3224 普通平衡树 splay模板题
- 平衡树之splay BZOJ3224 普通平衡树
- BZOJ3224:普通平衡树(含SBT、Treap、Splay模板)
- 【模板】【bzoj3224】Tyvj 1728 普通平衡树 Splay
- 【BZOJ3224】【codevs4543】【tyvj1728】普通平衡树,第一次的splay
- BZOJ3224+洛谷3369普通平衡树 splay版
- UVa101(模拟+基础数据结构vector)
- eclipse Alt+/提示老弹错误框
- java中完成九九乘法表
- Eclipse使用技巧
- MySQL 5.7主从复制从零开始设置及全面详解——实现多线程并行同步,解决主从复制延迟问题!
- 【bzoj3224】普通平衡树(splay板子)
- Linux下USB驱动框架分析 转
- 数据库事务隔离级别
- 不让bat文件运行命令结束后cmd窗口自动关闭
- 晋晨瑞
- 依存句法分析与语义依存分析的区别
- 微信小程序JSON数据提取问题
- 简易解说拉格朗日对偶(Lagrange duality)
- Android子线程间通信