3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2794 Solved: 1132
[ Submit][ Status]
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
题解: SBT的基础操作,复习用。
代码:
program pro;
var
s,l,r,ke:array[0..200000]of longint;
n,root,tot:longint;
procedure right(var now:longint);
var
tmp:longint;
begin
tmp:=l[now];
l[now]:=r[tmp];
r[tmp]:=now;
s[tmp]:=s[now];
s[now]:=s[l[now]]+s[r[now]]+1;
now:=tmp;
end;
procedure left(var now:longint);
var
tmp:longint;
begin
tmp:=r[now];
r[now]:=l[tmp];
l[tmp]:=now;
s[tmp]:=s[now];
s[now]:=s[l[now]]+s[r[now]]+1;
now:=tmp;
end;
procedure maintain(var now:longint; flag:boolean);
begin
if flag=false then
if s[l[l[now]]]>s[r[now]] then right(now)
else
if s[r[l[now]]]>s[r[now]] then
begin
left(l[now]);
right(now);
end
else exit
else
if s[r[r[now]]]>s[l[now]] then left(now)
else
if s[l[r[now]]]>s[l[now]] then
begin
right(r[now]);
left(now);
end
else exit;
maintain(l[now],false);
maintain(r[now],true);
maintain(now,true);
maintain(now,false);
end;
procedure insert(var now:longint; num:longint);
begin
if now=0 then
begin
inc(tot); now:=tot;
s[now]:=1; ke[now]:=num; l[now]:=0; r[now]:=0;
end
else
begin
inc(s[now]);
if num<ke[now] then insert(l[now],num)
else insert(r[now],num);
maintain(now,num>=ke[now]);
end;
end;
function delete(var now:longint; num:longint):longint;
begin
dec(s[now]);
if (num=ke[now])or(num<ke[now])and(l[now]=0)or(num>ke[now])and(r[now]=0) then
begin
delete:=ke[now];
if (l[now]=0)or(r[now]=0) then now:=l[now]+r[now]
else ke[now]:=delete(l[now],ke[now]+1);
end
else
if num<ke[now] then delete:=delete(l[now],num)
else delete:=delete(r[now],num);
end;
function rank(var now:longint; num:longint):longint;
begin
if now=0 then exit(1);
if num<=ke[now] then rank:=rank(l[now],num)
else rank:=s[l[now]]+1+rank(r[now],num);
end;
function select(var now:longint; num:longint):longint;
begin
if num=s[l[now]]+1 then exit(ke[now]);
if num<=s[l[now]] then select:=select(l[now],num)
else select:=select(r[now],num-s[l[now]]-1);
end;
function pre(var now:longint; num:longint):longint;
begin
if now=0 then exit(num);
if num<=ke[now] then pre:=pre(l[now],num)
else
begin
pre:=pre(r[now],num);
if pre=num then pre:=ke[now];
end;
end;
function succ(var now:longint; num:longint):longint;
begin
if now=0 then exit(num);
if ke[now]<=num then succ:=succ(r[now],num)
else
begin
succ:=succ(l[now],num);
if succ=num then succ:=ke[now];
end;
end;
procedure main;
var
ord,num,i,j:longint;
begin
root:=0; tot:=0;
readln(n);
for i:=1 to n do
begin
read(ord);
case ord of
1:
begin
readln(num);
insert(root,num);
end;
2:
begin
readln(num);
delete(root,num);
end;
3:
begin
readln(num);
writeln(rank(root,num));
end;
4:
begin
readln(num);
writeln(select(root,num));
end;
5:
begin
readln(num);
writeln(pre(root,num));
end;
6:
begin
readln(num);
writeln(succ(root,num));
end;
end;
end;
end;
begin
main;
end.