求陈启峰SBT平衡树源程序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求陈启峰SBT平衡树源程序相关的知识,希望对你有一定的参考价值。
求陈启峰SBT平衡树源程序
有没有退化版的Pascal程序?
整体较标准版更快,人字型数据例外,但竞赛中不大可能出现人字型数据
$inline on
program CQF_SBT;
const maxn=2000000;
var key,s,left,right,a,b:array[0..maxn] of longint;
tt,q:longint;
procedure init;
begin
readln(q);
for q:=1 to q do
readln(a[q],b[q]);
end;
procedure work;
var t,k:longint;
procedure right_rotate(var t:longint);inline;
begin
k:=left[t];
left[t]:=right[k];
right[k]:=t;
s[k]:=s[t];
s[t]:=s[left[t]]+s[right[t]]+1;
t:=k;
end;
procedure left_rotate(var t:longint);inline;
begin
k:=right[t];
right[t]:=left[k];
left[k]:=t;
s[k]:=s[t];
s[t]:=s[left[t]]+s[right[t]]+1;
t:=k;
end;
procedure insert(var t,v:longint);inline;
begin
if t=0 then begin
inc(tt);
t:=tt;
key[t]:=v;
s[t]:=1;
left[t]:=0;
right[t]:=0;
end
else begin
inc(s[t]);
if v<key[t] then begin
insert(left[t],v);
if s[left[left[t]]]>s[right[t]] then
right_rotate(t);
end
else begin
insert(right[t],v);
if s[right[right[t]]]>s[left[t]] then
left_rotate(t);
end;
end;
end;
function delete(var t:longint;v:longint):longint;inline;
begin
dec(s[t]);
if (v=key[t])or(v<key[t])and(left[t]=0)or(v>key[t])and(right[t]=0) then begin
delete:=key[t];
if (left[t]=0)or(right[t]=0) then
t:=left[t]+right[t]
else
key[t]:=delete(left[t],key[t]+1);
end
else
if v<key[t] then
delete:=delete(left[t],v)
else
delete:=delete(right[t],v);
end;
function find(var t,v:longint):boolean;inline;
begin
if t=0 then
exit(false);
if v<key[t] then
find:=find(left[t],v)
else
find:=(key[t]=v)or find(right[t],v);
end;
function rank(var t,v:longint):longint;inline;
begin
if t=0 then
exit(1);
if v<=key[t] then
rank:=rank(left[t],v)
else
rank:=s[left[t]]+1+rank(right[t],v);
end;
function select(var t:longint;k:longint):longint;inline;
begin
if k=s[left[t]]+1 then
exit(key[t]);
if k<=s[left[t]] then
select:=select(left[t],k)
else
select:=select(right[t],k-1-s[left[t]]);
end;
function pred(var t,v:longint):longint;inline;
begin
if t=0 then
exit(v);
if v<=key[t] then
pred:=pred(left[t],v)
else begin
pred:=pred(right[t],v);
if pred=v then
pred:=key[t];
end;
end;
function succ(var t,v:longint):longint;inline;
begin
if t=0 then
exit(v);
if key[t]<=v then
succ:=succ(right[t],v)
else begin
succ:=succ(left[t],v);
if succ=v then
succ:=key[t];
end;
end;
begin
tt:=0;
t:=0;
s[0]:=0;
for q:=1 to q do
case a[q] of
1:insert(t,b[q]);
2:delete(t,b[q]);
3:writeln(find(t,b[q]));
4:writeln(rank(t,b[q]));
5:writeln(select(t,b[q]));
6:writeln(pred(t,b[q]));
7:writeln(succ(t,b[q]));
end;
end;
begin
assign(input,'bst.in');
assign(output,'bst.out');
reset(input);
rewrite(output);
init;
work;
close(input);
close(output);
end. 参考技术A Splay Tree
Treap
Random AVL Tree
Size Ballanced Tree
----------------------AVL树---------------------
$inline on
program CQF_AVL;
uses math;
const maxn=2000000;
var key,s,left,right,h,a,b:array[0..maxn] of longint;
tt,q:longint;
procedure init;
begin
readln(q);
for q:=1 to q do
readln(a[q],b[q]);
end;
procedure work;
var t,k:longint;
procedure right_rotate(var t:longint);inline;
begin
k:=left[t];
left[t]:=right[k];
right[k]:=t;
s[k]:=s[t];
s[t]:=s[left[t]]+s[right[t]]+1;
h[t]:=max(h[left[t]],h[right[t]])+1;
h[k]:=max(h[left[k]],h[right[k]])+1;
t:=k;
end;
procedure left_rotate(var t:longint);inline;
begin
k:=right[t];
right[t]:=left[k];
left[k]:=t;
s[k]:=s[t];
s[t]:=s[left[t]]+s[right[t]]+1;
h[t]:=max(h[left[t]],h[right[t]])+1;
h[k]:=max(h[left[k]],h[right[k]])+1;
t:=k;
end;
procedure insert(var t,v:longint);inline;
begin
if t=0 then begin
inc(tt);
t:=tt;
key[t]:=v;
s[t]:=1;
h[t]:=0;
left[t]:=0;
right[t]:=0;
end
else begin
inc(s[t]);
if v<key[t] then begin
insert(left[t],v);
h[t]:=max(h[left[t]],h[right[t]])+1;
if h[left[t]]-h[right[t]]>1 then
if v<key[left[t]] then
right_rotate(t)
else begin
left_rotate(left[t]);
right_rotate(t);
end;
end
else begin
insert(right[t],v);
h[t]:=max(h[left[t]],h[right[t]])+1;
if h[right[t]]-h[left[t]]>1 then
if v>=key[right[t]] then
left_rotate(t)
else begin
right_rotate(right[t]);
left_rotate(t);
end;
end;
end;
end;
function delete(var t:longint;v:longint):longint;inline;
begin
dec(s[t]);
if (v=key[t])or(v<key[t])and(left[t]=0)or(v>key[t])and(right[t]=0) then begin
delete:=key[t];
if (left[t]=0)or(right[t]=0) then
t:=left[t]+right[t]
else
key[t]:=delete(left[t],key[t]+1);
end
else
if v<key[t] then
delete:=delete(left[t],v)
else
delete:=delete(right[t],v);
if t=0 then
exit;
h[t]:=max(h[left[t]],h[right[t]])+1;
if h[right[t]]-h[left[t]]>1 then
if h[right[right[t]]]>=h[left[right[t]]] then
left_rotate(t)
else begin
right_rotate(right[t]);
left_rotate(t);
end;
if h[left[t]]-h[right[t]]>1 then
if h[left[left[t]]]>=h[right[left[t]]] then
right_rotate(t)
else begin
left_rotate(left[t]);
right_rotate(t);
end;
end;
function find(var t,v:longint):boolean;inline;
begin
if t=0 then
exit(false);
if v<key[t] then
find:=find(left[t],v)
else
find:=(key[t]=v)or find(right[t],v);
end;
function rank(var t,v:longint):longint;inline;
begin
if t=0 then
exit(1);
if v<=key[t] then
rank:=rank(left[t],v)
else
rank:=s[left[t]]+1+rank(right[t],v);
end;
function select(var t:longint;k:longint):longint;inline;
begin
if k=s[left[t]]+1 then
exit(key[t]);
if k<=s[left[t]] then
select:=select(left[t],k)
else
select:=select(right[t],k-1-s[left[t]]);
end;
function pred(var t,v:longint):longint;inline;
begin
if t=0 then
exit(v);
if v<=key[t] then
pred:=pred(left[t],v)
else begin
pred:=pred(right[t],v);
if pred=v then
pred:=key[t];
end;
end;
function succ(var t,v:longint):longint;inline;
begin
if t=0 then
exit(v);
if key[t]<=v then
succ:=succ(right[t],v)
else begin
succ:=succ(left[t],v);
if succ=v then
succ:=key[t];
end;
end;
begin
tt:=0;
t:=0;
s[0]:=0;
h[0]:=-1;
for q:=1 to q do
case a[q] of
1:insert(t,b[q]);
2:delete(t,b[q]);
3:writeln(find(t,b[q]));
4:writeln(rank(t,b[q]));
5:writeln(select(t,b[q]));
6:writeln(pred(t,b[q]));
7:writeln(succ(t,b[q]));
end;
end;
begin
assign(input,'bst.in');
assign(output,'bst.out');
reset(input);
rewrite(output);
init;
work;
close(input);
close(output);
end.
-------------------------------Randomized Tree--------------------------------
$inline on
program CQF_BST;
const maxn=2000000;
var key,s,left,right,a,b:array[0..maxn] of longint;
tt,q:longint;
procedure init;
begin
readln(q);
for q:=1 to q do
readln(a[q],b[q]);
end;
procedure work;
var t,k:longint;
procedure right_rotate(var t:longint);inline;
begin
k:=left[t];
left[t]:=right[k];
right[k]:=t;
s[k]:=s[t];
s[t]:=s[left[t]]+s[right[t]]+1;
t:=k;
end;
procedure left_rotate(var t:longint);inline;
begin
k:=right[t];
right[t]:=left[k];
left[k]:=t;
s[k]:=s[t];
s[t]:=s[left[t]]+s[right[t]]+1;
t:=k;
end;
procedure randomizedinsert(var t,v:longint;pd:boolean);inline;
begin
if t=0 then begin
inc(tt);
t:=tt;
key[t]:=v;
left[t]:=0;
right[t]:=0;
s[t]:=1;
end
else begin
if not pd and(random(s[t]+1)=0) then
pd:=true;
inc(s[t]);
if v<key[t] then begin
randomizedinsert(left[t],v,pd);
if pd then
right_rotate(t);
end
else begin
randomizedinsert(right[t],v,pd);
if pd then
left_rotate(t);
end;
end;
end;
function delete(var t:longint;v:longint):longint;inline;
begin
dec(s[t]);
if (v=key[t])or(v<key[t])and(left[t]=0)or(v>key[t])and(right[t]=0) then begin
delete:=key[t];
if (left[t]=0)or(right[t]=0) then
t:=left[t]+right[t]
else
key[t]:=delete(left[t],key[t]+1);
end
else
if v<key[t] then
delete:=delete(left[t],v)
else
delete:=delete(right[t],v);
end;
function find(var t,v:longint):boolean;inline;
begin
if t=0 then
exit(false);
if v<key[t] then
find:=find(left[t],v)
else
find:=(key[t]=v)or find(right[t],v);
end;
function rank(var t,v:longint):longint;inline;
begin
if t=0 then
exit(1);
if v<=key[t] then
rank:=rank(left[t],v)
else
rank:=s[left[t]]+1+rank(right[t],v);
end;
function select(var t:longint;k:longint):longint;inline;
begin
if k=s[left[t]]+1 then
exit(key[t]);
if k<=s[left[t]] then
select:=select(left[t],k)
else
select:=select(right[t],k-1-s[left[t]]);
end;
function pred(var t,v:longint):longint;inline;
begin
if t=0 then
exit(v);
if v<=key[t] then
pred:=pred(left[t],v)
else begin
pred:=pred(right[t],v);
if pred=v then
pred:=key[t];
end;
end;
function succ(var t,v:longint):longint;inline;
begin
if t=0 then
exit(v);
if key[t]<=v then
succ:=succ(right[t],v)
else begin
succ:=succ(left[t],v);
if succ=v then
succ:=key[t];
end;
end;
begin
tt:=0;
t:=0;
s[0]:=0;
for q:=1 to q do
case a[q] of
1:randomizedinsert(t,b[q],false);
2:delete(t,b[q]);
3:writeln(find(t,b[q]));
4:writeln(rank(t,b[q]));
5:writeln(select(t,b[q]));
6:writeln(pred(t,b[q]));
7:writeln(succ(t,b[q]));
end;
end;
begin
assign(input,'bst.in');
assign(output,'bst.out');
reset(input);
rewrite(output);
init;
work;
close(input);
close(output);
end.
-------------------------Size Ballanced Tree-------------------------------
program CQF_SBT;
const maxn=2000000;
var key,s,left,right,a,b:array[0..maxn] of longint;
tt,q:longint;
procedure init;
begin
readln(q);
for q:=1 to q do
readln(a[q],b[q]);
end;
procedure work;
var t,k:longint;
procedure right_rotate(var t:longint); inline;
begin
k:=left[t];
left[t]:=right[k];
right[k]:=t;
s[k]:=s[t];
s[t]:=s[left[t]]+s[right[t]]+1;
t:=k;
end;
procedure left_rotate(var t:longint); inline;
begin
k:=right[t];
right[t]:=left[k];
left[k]:=t;
s[k]:=s[t];
s[t]:=s[left[t]]+s[right[t]]+1;
t:=k;
end;
procedure maintain(var t:longint;flag:boolean); inline;
begin
if flag=false then
if s[left[left[t]]]>s[right[t]] then
right_rotate(t)
else
if s[right[left[t]]]>s[right[t]] then begin
left_rotate(left[t]);
right_rotate(t);
end
else
exit
else
if s[right[right[t]]]>s[left[t]] then
left_rotate(t)
else
if s[left[right[t]]]>s[left[t]] then begin
right_rotate(right[t]);
left_rotate(t);
end
else
exit;
maintain(left[t],false);
maintain(right[t],true);
maintain(t,true);
maintain(t,false);
end;
procedure insert(var t,v:longint);inline;
begin
if t=0 then begin
inc(tt);
t:=tt;
key[t]:=v;
s[t]:=1;
left[t]:=0;
right[t]:=0;
end
else begin
inc(s[t]);
if v<key[t] then
insert(left[t],v)
else
insert(right[t],v);
maintain(t,v>=key[t]);
end;
end;
function delete(var t:longint;v:longint):longint;inline;
begin
dec(s[t]);
if (v=key[t])or(v<key[t])and(left[t]=0)or(v>key[t])and(right[t]=0) then begin
delete:=key[t];
if (left[t]=0)or(right[t]=0) then
t:=left[t]+right[t]
else
key[t]:=delete(left[t],key[t]+1);
end
else
if v<key[t] then
delete:=delete(left[t],v)
else
delete:=delete(right[t],v);
end;
function find(var t,v:longint):boolean;inline;
begin
if t=0 then
exit(false);
if v<key[t] then
find:=find(left[t],v)
else
find:=(key[t]=v)or find(right[t],v);
end;
function rank(var t,v:longint):longint;inline;
begin
if t=0 then
exit(1);
if v<=key[t] then
rank:=rank(left[t],v)
else
rank:=s[left[t]]+1+rank(right[t],v);
end;
function select(var t:longint;k:longint):longint;inline;
begin
if k=s[left[t]]+1 then
exit(key[t]);
if k<=s[left[t]] then
select:=select(left[t],k)
else
select:=select(right[t],k-1-s[left[t]]);
end;
function pred(var t,v:longint):longint;inline;
begin
if t=0 then
exit(v);
if v<=key[t] then
pred:=pred(left[t],v)
else begin
pred:=pred(right[t],v);
if pred=v then
pred:=key[t];
end;
end;
function succ(var t,v:longint):longint;inline;
begin
if t=0 then
exit(v);
if key[t]<=v then
succ:=succ(right[t],v)
else begin
succ:=succ(left[t],v);
if succ=v then
succ:=key[t];
end;
end;
begin
tt:=0;
t:=0;
s[0]:=0;
for q:=1 to q do
case a[q] of
1:insert(t,b[q]);
2:delete(t,b[q]);
3:writeln(find(t,b[q]));
4:writeln(rank(t,b[q]));
5:writeln(select(t,b[q]));
6:writeln(pred(t,b[q]));
7:writeln(succ(t,b[q]));
end;
end;
begin
assign(input,'bst.in');
assign(output,'bst.out');
reset(input);
rewrite(output);
init;
work;
close(input);
close(output);
end.
平衡二叉树的算法
参考技术ASize Balanced Tree(简称SBT)是一自平衡二叉查找树,是在计算机科学中用到的一种数据结构。它是由中国广东中山纪念中学的陈启峰发明的。陈启峰于2006年底完成论文《Size Balanced Tree》,并在2007年的全国青少年信息学奥林匹克竞赛冬令营中发表。由于SBT的拼写很容易找到中文谐音,它常被中国的信息学竞赛选手和ACM/ICPC选手们戏称为“傻B树”、“Super BT”等。相比红黑树、AVL树等自平衡二叉查找树,SBT更易于实现。据陈启峰在论文中称,SBT是“目前为止速度最快的高级二叉搜索树”。SBT能在O(log n)的时间内完成所有二叉搜索树(BST)的相关操作,而与普通二叉搜索树相比,SBT仅仅加入了简洁的核心操作Maintain。由于SBT赖以保持平衡的是size域而不是其他“无用”的域,它可以很方便地实现动态顺序统计中的select和rank操作。
以上是关于求陈启峰SBT平衡树源程序的主要内容,如果未能解决你的问题,请参考以下文章
竞赛最好用的平衡树-Size Balanced Tree(SBT)建议收藏
BZOJ 3224 普通平衡树 平衡树的两种姿势:SBT,splay
替罪羊树 ------ luogu P3369 模板普通平衡树(Treap/SBT)