博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 3224,tyvj 1728普通平衡树
阅读量:5249 次
发布时间:2019-06-14

本文共 4052 字,大约阅读时间需要 13 分钟。

这道题涵盖了平衡树的基本操作。。。

先关注操作三,它指出要输出最小的排名,因此我们可以将重复的元素存在一个节点内,代码实现很简单。。。

插入操作已讲。。。

那么怎样删除呢?

首先我们找到被删的点,如果它是重复的(该元素还剩很多个),那么就把个数减一即可。

否则我们可以采用像堆的方式,将这个元素通过旋转不断地下移。。。

问题来了,下移的时候是选择左旋还是右旋呢?

左旋是将右边的点换到上面,右旋是将左边的点换到上面,由于我的随机值是大根堆(大的在下,小的在上)。那么我就应该把随机值小的儿子旋到上面来。(和堆的原理一样)根据这个来决定是左旋还是右旋。。旋转后将当前点移动到旋转的那个儿子上[旋转后原来的点就变成了儿子,儿子正是原来的点];就这样反复执行,直到当前点的两个儿子都为Null 了[注:Null是本人造出来的值,为了弥补指针的不足,具体详见代码] ,就把当前点变为Null,就成功删去啦!

怎样用平衡树来查前驱呢?

如果我们要查点x的前驱,从root开始, 如果当前点的值是小于x点的,那么前驱有可能在当前点的右子树中,但当前点的的右子树中的所有点可能都大于x点,所以前驱也有可能就是当前点。。。面对这种情况我们应先搜右子树,看有没有结果,然后确定答案;如果当前点是大于等于x点的,那么很显然前驱在当前点的左子树中,就把当前点变为左儿子就行了

查后继的事情就交给读者自己想了。

至于3,4两个查询操作,对于读者来说也很简单了,就不说了。。

那么基本的treap模板就打出来了

#include
#include
#include
#include
#include
#include
#include
#include
#include
const int N = 1e5 + 7,INF = 0x7fffffff;#define Ran1221() ((rand() << 13) + (rand() << 6) + rand ())#define Ran12() (Ran1221() + Ran1221() + Ran1221() + 1)class Treap { private : struct Node { Node *son[2]; int size,num,data,hr; Node () {} Node (int data,Node *fl) : data(data) { size = num = 1; son[0] = son[1] = fl; hr = Ran12(); } void update () { size = son[0] -> size + son[1] -> size + num; } }*pool,*Null,*root,meme[N]; int ball; void rotate (Node *&T,bool v) { Node *Tt = T -> son[v]; T -> son[v] = Tt -> son[v^1]; Tt -> son[v^1] = T; T -> update(); Tt -> update(); T = Tt; } int Precursor (Node *&T) { if(T == Null) return T -> data; if(T -> data >= ball) return Precursor (T -> son[0]); int k = Precursor (T -> son[1]); if(k == Null -> data) return T -> data; return k; } int Subsequent (Node *&T) { if(T == Null) return T -> data; if(T -> data <= ball) return Subsequent (T -> son[1]); int k = Subsequent (T -> son[0]); if(k == Null -> data) return T -> data; return k; } void Print (Node *&T) { if(T == Null) return ; Print (T -> son[0]); for(int i=1;i<=T->num;++i) printf("%d ",T -> data); Print (T -> son[1]); } void Insert (Node *&T) { if(T == Null) { T = new (pool++) Node (ball,Null); return; } if(T -> data == ball) { ++ T -> num; ++ T -> size; return ; } int v = ball > T -> data; Insert (T -> son[v]); if(T -> son[v] -> hr < T -> hr) rotate (T,v); else T -> update(); } int sum; void Rank (Node *&T) { if(T == Null) return ; if(T -> data > ball) Rank (T -> son[0]); else { sum += T -> son[0] -> size; if(T -> data < ball) sum += T -> num , Rank (T -> son[1]); } } void Delete (Node *&T) { if(T == Null) return ; if(T -> data == ball) { if(T -> num > 1) { -- T -> num; -- T -> size; return ; } if(T -> son[0] == Null || T -> son[1] == Null) { int v = T -> son[1] != Null; T = T -> son[v]; return ; } int v = T -> son[1] -> hr < T -> son[0] -> hr; rotate (T,v); Delete (T -> son[v^1]); } else { int v = ball > T -> data; Delete (T -> son[v]); } T -> update(); } int TheNo (Node *&T) { if(T == Null) return 0; if(ball <= T -> son[0] -> size) return TheNo (T -> son[0]); if(ball <= T -> son[0] -> size + T -> num) return T -> data; ball -= T -> son[0] -> size + T -> num; return TheNo (T -> son[1]); } public : Treap () { Null = new Node (); Null -> size = Null -> num = 0; Null -> data = -INF;} void Pri () { Print(root); } void clear () { pool = meme; root = Null; } void Ins (int xxx) { ball = xxx; Insert(root); } int Ran (int xxx) { ball = xxx; sum = 0; Rank (root); return sum; } void Del (int xxx) { ball = xxx; Delete(root); } int The (int xxx) { ball = xxx; return TheNo(root); } int Pre (int xxx) { ball = xxx; return Precursor(root);} int Sub (int xxx) { ball = xxx; return Subsequent(root); } }treap;int opt,w,Q;int main () { freopen("3224.in","r",stdin); freopen("3224.out","w",stdout); scanf("%d",&Q); treap.clear(); while (Q--) { scanf("%d%d",&opt,&w); if(opt == 1) treap . Ins(w); if(opt == 2) treap . Del(w); if(opt == 3) printf("%d\n",treap . Ran(w) + 1); if(opt == 4) printf("%d\n",treap . The(w)); if(opt == 5) printf("%d\n",treap . Pre(w)); if(opt == 6) printf("%d\n",treap . Sub(w)); } return 0;}

That is all , thank you for watching.

转载于:https://www.cnblogs.com/dcoi-king/p/5353662.html

你可能感兴趣的文章
基本排序
查看>>
前端非对称加密,后端Node.js解密(jsencrypt插件)(不需要密钥转码)
查看>>
list删除、集合遍历删除
查看>>
趣谈Java变量的可见性问题
查看>>
图标字体制作 -- 将SVG制作成图标字体文件,通过引入使用
查看>>
为Eclipse添加C/C++开发工具
查看>>
杭州互联网公司汇总
查看>>
Sublime text3 注册失效解决方法
查看>>
C# 强制关闭当前程序进程(完全Kill掉不留痕迹)
查看>>
ssm框架之将数据库的数据导入导出为excel文件
查看>>
hdu 4284 Travel(压缩DP,4级)
查看>>
easy_install
查看>>
hdu 1423 Greatest Common Increasing Subsequence(DP 最长公共上升子序列)
查看>>
【Log4j】分包,分等级记录日志信息
查看>>
语音识别中的MFCC的提取原理和MATLAB实现
查看>>
初识Treap
查看>>
openLDAP环境搭建
查看>>
Spring和Mybatis的集成
查看>>
玩转UICollectionViewLayout
查看>>
如何在.xml文件中配置Servlet信息
查看>>