Review-SBT(Bzoj3224)

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 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

Sample Output

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


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值