【学校OJ】avl平衡树 普通平衡树
2017-03-28 14:00
246 查看
题目描述
你需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入一个整数x
2. 删除一个整数x(若有多个相同的数,只删除一个)
3. 查询整数x的排名(若有多个相同的数,输出最小的排名),相同的数依次排名,不并列排名
4. 查询排名为x的数,排名的概念同3
5. 求x的前驱(前驱定义为小于x,且最大的数),保证x有前驱
6. 求x的后继(后继定义为大于x,且最小的数),保证x有后继
输入
第一行为n,表示操作的个数(n <= 500000)下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6, -10^7 <= x <= 10^7)
大规模输入数据,建立读入优化
输出
对于操作3,4,5,6每行输出一个数,表示对应答案
样例输入
Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)8 1 10 1 20 1 30 3 20 4 2 2 10 5 25 6 -1
样例输出
2 20 20 20
好久没诈尸了,不太爽。所以又来一发。。。
学了avl平衡树,才懂得了什么叫做200行代码。。。然而平衡树写得也是一道猥琐过一道,那么就选取最经典的普通平衡树作为这次诈尸的工具吧!
题目与题目描述很直接的告诉了我们——平衡树!所以我们可以很容易分析出实现的方法。
结构体成员配备:左儿子ls,右儿子rs,数值data,高度h,同样数量sum,总结点size(包括左子树、右子树、自己)
维护方式:ls、rs用旋转维护,data永不变更,h取ls和rs的最大h加1,sum删除插入时维护。size在各种时候都别忘了用ls的size、rs的size和sum相加进行维护
1.插入节点。这种简单粗暴的事情还需要说吗?直接进行一般的插入,由于使用惰性删除,所以我们可以遇到相同节点就将sum++,就很容易的解决了!当然你也可以用普通删除然后就保存相同节点啦~
2.删除节点。你们会插入了还不会删除吗?懒人就用惰性删除,你要是真的喜欢普通删除或者希望能过(是的,惰性删除偏偏在学校OJ上过不了TAT,不过大部分OJ都是可以过的),就使用删除后慢慢转到顶部……
3.查询数的排名。这就比较简单了,因为数是一定存在的,所以只要找到一个节点,然后比较大小即可。惰性删除很好解决排名问题,如果刚好等于,只需输出最小的即可,即avl[avl[x].ls].size+1,看出来了吗?ls全体比自己小,排名只需加一,如果比自己小就往ls找,大的话就加上ls的size和sum,再往rs找即可。直接删除就方便了,处理方法一模一样,只是找到一样的后要先记录一下,再往ls那边找(因为有可能有重复的)。
4.查询排名的数。就是3的逆操作,依然是比较ls的size就完了,自己慢慢思考吧……还不需要考虑重复的问题
5.前驱,后继。由于操作过于相似,可以当成一种来看。
直接删除:如果遇到一个节点,比较大小,然后很直接地转入ls或rs即可,不需要考虑其他的。
惰性删除:这就比较麻烦了,如果遇到节点,且sum不为0,那么只需要直接转入ls或rs,因为至少有data比另外一边更接近这个数。但是如果sum为0,就不得不两边兼顾一下,不然很有可能某一边虽然不为空,但可能没有一个符合,现在就只能判断一下是否为空,然后慢慢两边搜……这会浪费一些时间……
至此,我一句代码也没有给你们,然后将这道题讲完了~当然不能坑你们,代码来了(200行+)~
#include<cstd 4000 io> #include<algorithm> #include<climits> using namespace std; const int inf=100000000; int n,cnt,lmax,rmin,root,ans; inline int getint() { register int f=1,p=0; register char c=getchar(); while((c<'0'||c>'9')&&c!='-') c=getchar(); if(c=='-') { f=-1;c=getchar(); } for(;c>='0'&&c<='9';) { p=p*10+c-'0'; c=getchar(); } p*=f; return p; } inline void putint(int p) { if(p<0) { putchar('-'); p=-p; } if(p>9)putint(p/10); putchar(p%10+'0'); } struct avl { int ls,rs,p,h,si,sum; }d[500005]; inline int zig(int r) { register int t=d[r].ls; d[r].ls=d[t].rs; d[t].rs=r; d[r].h=max(d[d[r].rs].h,d[d[r].ls].h)+1; d[t].h=max(d[d[t].rs].h,d[d[t].ls].h)+1; d[r].si=d[d[r].ls].si+d[d[r].rs].si+d[r].sum; d[t].si=d[d[t].ls].si+d[d[t].rs].si+d[r].sum; return t; } inline int zag(int r) { register int t=d[r].rs; d[r].rs=d[t].ls; d[t].ls=r; d[r].h=max(d[d[r].rs].h,d[d[r].ls].h)+1; d[t].h=max(d[d[t].rs].h,d[d[t].ls].h)+1; d[r].si=d[d[r].ls].si+d[d[r].rs].si+d[r].sum; d[t].si=d[d[t].ls].si+d[d[t].rs].si+d[r].sum; return t; } inline int zigzag(int r) { d[r].rs=zig(d[r].rs); r=zag(r); return r; } inline int zagzig(int r) { d[r].ls=zag(d[r].ls); r=zig(r); return r; } inline void move(int &q) { if(d[d[q].ls].h-d[d[q].rs].h==2) { register int t=d[q].ls; if(d[d[t].ls].h>d[d[t].rs].h) q=zig(q); else q=zagzig(q); } else { if(d[d[q].ls].h-d[d[q].rs].h==-2) { register int t=d[q].rs; if(d[d[t].rs].h>d[d[t].ls].h) q=zag(q); else q=zigzag(q); } } d[q].si=d[d[q].ls].si+d[d[q].rs].si+d[q].sum; d[q].h=max(d[d[q].ls].h,d[d[q].rs].h)+1; } inline void insert(int a,int &q) { if(q==0) { q=++cnt; d[q].p=a; d[q].h=1; d[q].si=1; d[q].sum=1; return; } if(d[q].p==a) d[q].sum++; else { if(d[q].p>a) insert(a,d[q].ls); else insert(a,d[q].rs); } move(q); } inline void dele(int a,int q) { if(q==0)return; if(d[q].p==a) d[q].sum--; else { if(a<d[q].p) dele(a,d[q].ls); else dele(a,d[q].rs); } d[q].si=d[d[q].ls].si+d[d[q].rs].si+d[q].sum; } inline int find(int k,int q) { if(q==0)return inf; register int l=d[q].sum; if(k>=d[d[q].ls].si+1&&k<=d[d[q].ls].si+l)return d[q].p; else { if(k<d[d[q].ls].si+1)return find(k,d[q].ls); else return find(k-d[d[q].ls].si-l,d[q].rs); } } inline int ask(int k,int q) { if(q==0)return inf; if(d[q].p==k) return d[d[q].ls].si+1; else { if(k<d[q].p) return ask(k,d[q].ls); else return ask(k,d[q].rs)+d[d[q].ls].si+d[q].sum; } } inline void left(int x,int q) { if(q==0)return; if(d[q].p<x) { if(d[q].sum) lmax=max(lmax,d[q].p); else left(x,d[q].ls); if(d[d[q].rs].si) left(x,d[q].rs); } else left(x,d[q].ls); } inline void right(int x,int q) { if(q==0)return; if(d[q].p>x) { if(d[q].sum) rmin=min(rmin,d[q].p); else right(x,d[q].rs); if(d[d[q].ls].si) right(x,d[q].ls); } else right(x,d[q].rs); } int main() { n=getint(); for(int i=1;i<=n;i++) { register int opt,p; opt=getint();p=getint(); if(opt==1) { insert(p,root); continue; } if(opt==2) { dele(p,root); continue; } if(opt==3) { ans=ask(p,root); putint(ans); } if(opt==4) { ans=find(p,root); putint(ans); } if(opt==5) { lmax=-inf; left(p,root); putint(lmax); } if(opt==6) { rmin=inf; right(p,root); putint(rmin); } putchar('\n'); } }
我不会说这段代码是会超时的……
相关文章推荐
- 【学校OJ】 avl平衡树+线段树 二逼平衡树
- 【BZOJ】3224: Tyvj 1728 普通平衡树(某不科学的oj)
- 【学校OJ】 splay平衡树 文艺平衡树
- bzoj 3224 普通平衡树 vactor的妙用
- (vector通过)bzoj3224: Tyvj 1728 普通平衡树
- 李开复:普通学校的毕业生如何进入Google
- 【BZOJ3224】【codevs4543】【tyvj1728】普通平衡树,第一次的splay
- 【模板】普通平衡树(洛谷3369/大视野3224)splay_tree
- 【模板】【Treap/SBT】【树堆】普通平衡树【洛谷P3369】
- 【BZOJ】【P3224】【普通平衡树】
- bzoj 3224: Tyvj 1728 普通平衡树
- BZOJ 3224 Tyvj 1728 普通平衡树
- 不同学校的OJ
- [Tyvj 1728]普通平衡树
- BZOJ3224/洛谷P3391 - 普通平衡树(Splay)
- 3224: Tyvj 1728 普通平衡树(新板子)
- [学习笔记] bzoj3224 普通平衡树:splay模板
- 【BZOJ3224】普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树 [Splay]【数据结构】
- 3224: Tyvj 1728 普通平衡树