求陈启峰SBT平衡树源程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求陈启峰SBT平衡树源程序相关的知识,希望对你有一定的参考价值。

求陈启峰SBT平衡树源程序
有没有退化版的Pascal程序?

SBT 2.0 退化版

整体较标准版更快,人字型数据例外,但竞赛中不大可能出现人字型数据

$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.

平衡二叉树的算法

参考技术A

Size 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

P3369 模板普通平衡树(Treap/SBT)

替罪羊树 ------ luogu P3369 模板普通平衡树(Treap/SBT)

平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板超详解

红黑树 ------ luogu P3369 模板普通平衡树(Treap/SBT)