P3369 模板 普通平衡樹

2022-04-30 19:03:11 字數 4429 閱讀 3534

這道題最簡單的解法:權值線段樹

下面的程式為了方便大家理解沒有離散化哦。

操作 \(i\) / \(ii\): 插入 / 刪除 \(x\) 數

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 dec(j);

if i<=j then begin swap(sortn[i],sortn[j]); inc(i); dec(j); end;

until i>=j;

if il 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.

P3369 模板 普通平衡樹

題目描述 您需要寫一種資料結構 可參考題目標題 來維護一些數,其中需要提供以下操作 1 插入x數 2 刪除x數 若有多個相同的數,因只刪除乙個 3 查詢x數的排名 排名定義為比當前數小的數的個數 1。若有多個相同的數,因輸出最小的排名 4 查詢排名為x的數 5 求x的前驅 前驅定義為小於x,且最大的...

P3369 模板 普通平衡樹

aimee 考試前看到某份考綱提到了平衡樹 突發奇想想學乙個 但是來不及了,為了平衡學習時間,以及大佬的建議下,毅然決定用vector搞乙個 額,要是vector都過不了,那以我的水平,也拿不到更多的分了 配方,lower bound upper bound vector 對於操作1,使用vecto...

P3369 模板 普通平衡樹

1.插入x數 2.刪除x數 若有多個相同的數,因只刪除乙個 3.查詢x數的排名 排名定義為比當前數小的數的個數 1。若有多個相同的數,因輸出最小的排名 4.查詢排名為x的數 5.求x的前驅 前驅定義為小於x,且最大的數 6.求x的後繼 後繼定義為大於x,且最小的數 輸入格式 第一行為n,表示操作的個...