P3369 【模板】普通平衡树
这道题最简单的解法: 权值线段树。
-
代码行数: \(48\)。
-
难度: \(Splay\) 的 \(\frac{1}{10}\) 不到。
下面的程序为了方便大家理解没有离散化哦。
操作 \(I\) / \(II\): 插入 / 删除 \(x\) 数
直接写一个 \(Change\) 函数代表在线段树的 \(x\) 这个位置 \(±1\)。
procedure Change(l,r,k,key,add:longint);
var mid:longint;
begin
inc(tree[k],add); if l=r then exit;
mid:=(l+r) >> 1;
if key<=mid then Change(l,mid,k << 1,key,add)
else Change(mid+1,r,k << 1+1,key,add);
end;
操作 \(III\): 查询 \(x\) 数的排名
利用第 \(K\) 大的方法,可以发现我们在权值线段树中往右跑的时候应该加上左儿子的权值。最后到了要加上自己的一名。
function Query_number_rank(l,r,k,key:longint):longint;
var mid:longint;
begin
Query_number_rank:=0;
if l=r then exit(1);
mid:=(l+r) >> 1;
if key<=mid then inc(Query_number_rank,Query_number_rank(l,mid,k << 1,key)) else
begin inc(Query_number_rank,tree[k << 1]); inc(Query_number_rank,Query_number_rank(mid+1,r,k << 1+1,key)); end;
end;
操作 \(IV\): 查询排名为 \(x\) 的数
直接查询第 \(K\) 大就好啦。
function Query_rank_number(l,r,k,key:longint):longint;
var mid:longint;
begin
if l=r then exit(l);
mid:=(l+r) >> 1;
if tree[k << 1]>=key then Query_rank_number:=Query_rank_number(l,mid,k << 1,key)
else Query_rank_number:=Query_rank_number(mid+1,r,k << 1+1,key-tree[k << 1]);
end;
操作 \(V\): 求 \(x\) 的前驱
求 \(x\) 的前驱可以转化为找 \(rank[x]-1\) 的数什么,然后直接搞。
if order=5 then writeln(Query_rank_number(1,border,1,Query_number_rank(1,border,1,k)-1));
操作 \(VI\): 求 \(x\) 的后继
考虑到直接像 \(V\) 一样查后继可能是数本身 (如果有很多个同样的数字),那么我们可以记录一下每一个数字的出现次数为 \(bucket[x]\),然后直接搞。
if order=6 then writeln(Query_rank_number(1,border,1,Query_number_rank(1,border,1,k)+bucket[k]));
\(Code\)
离散化后的 \(100\) 分。(这数据强度真的是醉了)
var
num,sortn,order:array[-1..110000] of longint;
dis:array[-11000000..11000000] of longint;
recf,bucket:array[-1..110000] of longint;
tree:array[-1..810000] of longint;
i,k,n,head,tail,border:longint;
procedure Swap(var x,y:longint);var t:longint; begin t:=x; x:=y; y:=t; end;
procedure Sort(l,r:longint);
var i,j,s:longint;
begin
i:=l; j:=r; s:=sortn[(l+r) >> 1];
repeat
while sortn[i]<s do inc(i);
while sortn[j]>s do dec(j);
if i<=j then begin Swap(sortn[i],sortn[j]); inc(i); dec(j); end;
until i>=j;
if i<r then Sort(i,r);
if j>l then Sort(l,j);
end;
procedure Change(l,r,k,key,add:longint);
var mid:longint;
begin
inc(tree[k],add); if l=r then exit;
mid:=(l+r) >> 1;
if key<=mid then Change(l,mid,k << 1,key,add)
else Change(mid+1,r,k << 1+1,key,add);
end;
function Query_number_rank(l,r,k,key:longint):longint;
var mid:longint;
begin
Query_number_rank:=0;
if l=r then exit(1);
mid:=(l+r) >> 1;
if key<=mid then inc(Query_number_rank,Query_number_rank(l,mid,k << 1,key)) else
begin inc(Query_number_rank,tree[k << 1]); inc(Query_number_rank,Query_number_rank(mid+1,r,k << 1+1,key)); end;
end;
function Query_rank_number(l,r,k,key:longint):longint;
var mid:longint;
begin
if l=r then exit(l);
mid:=(l+r) >> 1;
if tree[k << 1]>=key then Query_rank_number:=Query_rank_number(l,mid,k << 1,key)
else Query_rank_number:=Query_rank_number(mid+1,r,k << 1+1,key-tree[k << 1]);
end;
begin
read(n);
for i:=1 to n do begin read(order[i],num[i]); if (order[i]<=2)or(order[i]>=5) then begin inc(head); sortn[head]:=num[i]; end; end;
Sort(1,head);
for i:=1 to head do if sortn[i]<>sortn[i-1] then begin inc(tail); dis[sortn[i]]:=tail; recf[tail]:=sortn[i]; end;
border:=tail;
for i:=1 to n do
begin
if order[i]=1 then begin inc(bucket[dis[num[i]]]); Change(1,border,1,dis[num[i]],1); end;
if order[i]=2 then begin dec(bucket[dis[num[i]]]); Change(1,border,1,dis[num[i]],-1); end;
if order[i]=3 then writeln(Query_number_rank(1,border,1,dis[num[i]]));
if order[i]=4 then writeln(recf[Query_rank_number(1,border,1,num[i])]);
if order[i]=5 then writeln(recf[Query_rank_number(1,border,1,Query_number_rank(1,border,1,dis[num[i]])-1)]);
if order[i]=6 then writeln(recf[Query_rank_number(1,border,1,Query_number_rank(1,border,1,dis[num[i]])+bucket[dis[num[i]]])]);
end;
end.
完结撒花!✿✿ヽ(゚▽゚)ノ✿