平衡的美 treap
来源:互联网 发布:苹果怎么卸载软件 编辑:程序博客网 时间:2024/06/12 00:53
简单易学的平衡树,虽然随机值要靠rp,但一般来说还是不会被卡的。
treap=tree+heap,treap有两个关键值,id和权值。
一般的二叉排序树难以维持自身平衡,容易退化成链,所以就有了id值。
id靠随机,对我们来说无实际意义,由堆序维护,听起来有点搞笑,但确实在大多数情况下能维护平衡。
w是节点自身属性,对我们来说有实际意义,遵循二叉排序树的规则,即根节点左子树均小于根,右子树均大于根,递归定义。
由于treap兼有二者特点,所以维护的时候,不能单一的按tree或heap来,于是诞生了旋转的操作,既能维护堆序,又能维护树序。
在treap中分为左旋和右旋两种:
右旋
1 1
\ \
2 3
/ \ ——————> / \
3 4 5 2
/ \
5 4
左旋
1 1
\ \
2 4
/ \ ——————> / \
3 4 2 5
\ /
5 3
插入,先按二叉排序树插入,再维护id堆序(左旋,右旋实现,同时维护信息)
删除,找到指定节点,不断通过左旋右旋下沉,下沉至链节点(至少有一个子树为空)用其不为空子节点代替
基本操作就这些,还附带找k大,k小值等等操作
推荐模板http://blog.csdn.net/cjoilmd/article/details/6629062
lmd同学借助splay模板,写的非递归版treap,同时还有易错点。
总的来说,调试起来不是一般的麻烦,还是左偏树好调试。
const maxr=100000;var n,m,ss,ll,rr:longint; size,l,r,w,id,rt,a:array[0..200000]of longint; x,y,q,z,ans:array[0..500000]of longint; check:longint;function max(x,y:longint):longint;begin if x>y then exit(x) else exit(y)end;function min(x,y:longint):longint;begin if x<y then exit(x) else exit(y)end;procedure right(x:longint);var y,z:longint;begin y:=rt[x];z:=rt[y]; if l[z]=y then l[z]:=x else r[z]:=x;rt[x]:=z; l[y]:=r[x];rt[r[x]]:=y; r[x]:=y;rt[y]:=x; size[x]:=size[y]; size[y]:=size[l[y]]+size[r[y]]+1end;procedure left(x:longint);var y,z:longint;begin y:=rt[x];z:=rt[y]; if l[z]=y then l[z]:=x else r[z]:=x;rt[x]:=z; r[y]:=l[x];rt[l[x]]:=y; l[x]:=y;rt[y]:=x; size[x]:=size[y]; size[y]:=size[l[y]]+size[r[y]]+1end;function ori(x,y:longint):longint;begin inc(ss);id[ss]:=random(maxr); w[ss]:=x;size[ss]:=1; l[ss]:=0;r[ss]:=0;rt[ss]:=y; ori:=ssend;procedure ins(p:longint);var x:longint;begin x:=1; while true do begin inc(size[x]); if p>w[x] then begin if r[x]=0 then begin r[x]:=ori(p,x);x:=r[x];break end else x:=r[x] end else begin if l[x]=0 then begin l[x]:=ori(p,x);x:=l[x];break end else x:=l[x] end end; while id[x]<id[rt[x]] do if l[rt[x]]=x then right(x) else left(x)end;procedure low(x:longint);var ll,rr:longint;begin ll:=l[x];rr:=r[x]; if id[ll]<id[rr] then right(ll) else left(rr)end;procedure del(p:longint);var x,y,z:longint;begin x:=1; while w[x]<>p do if w[x]<p then x:=r[x] else x:=l[x]; id[x]:=maxlongint; while (l[x]<>0)and(r[x]<>0) do low(x); y:=rt[x]; if l[x]=0 then z:=r[x] else z:=l[x]; if l[y]=x then l[y]:=z else r[y]:=z; if z<>0 then rt[z]:=y; while id[y]<>-maxlongint do begin dec(size[y]); y:=rt[y] end; dec(size[y])end;function findmin(q:longint):longint;var x:longint;begin x:=1;inc(q); while true do begin if q=size[l[x]]+1 then exit(w[x]) else if q<=size[l[x]] then x:=l[x] else begin q:=q-size[l[x]]-1; x:=r[x] end endend;procedure work;var i,j:longint;begin rr:=0;x[0]:=x[1]; for i:=1 to m do begin for j:=x[i-1] to min(x[i]-1,y[i-1]) do del(a[j]); for j:=max(rr+1,x[i]) to y[i] do ins(a[j]); ans[z[i]]:=findmin(q[i]);rr:=y[i] endend;procedure qsort(l,r:longint);var i,j,xx,yy,c:longint;begin i:=l;j:=r;xx:=x[(l+r)>>1];yy:=y[(l+r)>>1]; repeat while (x[i]<xx)or((x[i]=xx)and(y[i]<yy)) do inc(i); while (xx<x[j])or((xx=x[j])and(yy<y[j])) do dec(j); if not(i>j) then begin c:=x[i];x[i]:=x[j];x[j]:=c; c:=y[i];y[i]:=y[j];y[j]:=c; c:=q[i];q[i]:=q[j];q[j]:=c; c:=z[i];z[i]:=z[j];z[j]:=c; inc(i);dec(j) end until i>j; if i<r then qsort(i,r); if l<j then qsort(l,j)end;procedure init;var i:longint;begin readln(n,m); for i:=1 to n do read(a[i]);readln; for i:=1 to m do begin readln(x[i],y[i],q[i]); z[i]:=i end; qsort(1,m); id[1]:=-maxlongint;w[1]:=-maxlongint;ss:=1; size[0]:=0; work; for i:=1 to m do writeln(ans[i])end;begin randomize; initend.
- 平衡的美 treap
- Treap--简单的平衡二叉搜索树
- 二叉排序树,平衡二叉树,Treap平衡树的实现-转帖
- TREAP平衡树代码
- Treap平衡树
- Treap平衡树
- Treap平衡树
- Treap平衡树
- TREAP平衡树
- 平衡树Treap模版
- 【平衡树】Treap
- 平衡树Treap
- 平衡树之treap
- 普通平衡树 treap
- 【学习】Treap平衡树
- 数据结构 平衡树treap
- 平衡树之Treap
- Treap-普通平衡树
- This attribute must be localized.错误解决方式
- ios view与view间切换的动画效果
- 一个软件工程师的职业规划
- JDK7正式版发布了!
- 栈的应用——计算表达式
- 平衡的美 treap
- 解决 android如何设置全屏模式
- ResultSet 简单介绍
- 在eclipse中打包apk
- Discuz!7以上让置顶用户发帖时权限默认为255
- hdu1027
- 命令行svn:ignore的用法
- 磁盘阵列 和 双机备份(一)
- C++学习过程中的补遗的零散知识点(1)