東東的舞會 (小根堆)

2021-07-24 07:59:33 字數 2755 閱讀 8903

東東的舞會(dance.pas/.c/.cpp)

題目描述

東東的幼兒園舉辦舞會,一共有n個小朋友參加。

老師讓所有的小朋友站成一列,從左開始編號,最左邊的小朋友編號為1,最右邊的為n。每個小朋友跳舞的熟練度我們用乙個整數來表示,第i個小朋友的熟練度為ai,每次相鄰小朋友熟練度最接近的一對會出列跳舞,如果有多對那麼最左邊的那一對會先出列。

東東是個愛思考的孩子,他想如果出列的小朋友不再回到隊伍當中的話,那麼出列的順序是什麼樣的呢?

輸入格式

第一行是乙個正整數 n。

第二行n個由空格隔開的正整數,第i個正整數ai,表示佇列中第i個小朋友的跳舞熟練度。

輸出格式

一行,表示按順序出列的小朋友的編號。(一對小朋友編號小的在前。)

樣例輸入

5 5 3 2 1 8

樣例輸出

2 3 1 4

資料範圍與約定

對於 40% 的資料,1≤n≤1000

對於 100% 的資料,1≤n≤10000,1≤ai≤100000

看到題目第一眼就知道是堆,寫了很久,但是評測之後發現資料很水,同學的暴力列舉都能ac。

模擬賽的解題報告如下:

自己維護小根堆然後瞬間ac的**:

program mys;

var i,j,k,m,n,nn,t,tt,t1,t2:longint;

a,f,l,r,zz,yy:array[0..300000]of longint;

b:array[0..300000]of boolean;

procedure

put(x,y:longint);

var p,tt:longint;

begin

inc(t);

f[t]:=abs(a[x]-a[y]);

l[t]:=x; r[t]:=y;

tt:=t;

while (tt>1)and((f[tt]div

2])or((f[tt]=f[tt div

2])and(l[tt]div

2]))) do

begin

p:=f[tt]; f[tt]:=f[tt div

2]; f[tt div

2]:=p;

p:=l[tt]; l[tt]:=l[tt div

2]; l[tt div

2]:=p;

p:=r[tt]; r[tt]:=r[tt div

2]; r[tt div

2]:=p;

tt:=tt div

2;end;

end;

procedure

pop;

var p,tt,son:longint;

begin

f[1]:=f[t];

l[1]:=l[t];

r[1]:=r[t];

dec(t);

tt:=1;

while (tt*2

<=t) do

begin

if (tt*2+1>t) or ((f[tt*2])2+1])or((f[tt*2]=f[tt*2+1])and(l[tt*2]2+1])) then

son:=tt*2

else son:=tt*2+1;

if (f[son]or((f[tt]=f[son])and(l[son]then

begin

p:=f[tt]; f[tt]:=f[son]; f[son]:=p;

p:=l[tt]; l[tt]:=l[son]; l[son]:=p;

p:=r[tt]; r[tt]:=r[son]; r[son]:=p;

tt:=son;

endelse

break;

end;

end;

begin

assign(input,'dance.in');reset(input);

assign(output,'dance.out');rewrite(output);

readln(n);

nn:=n;

for i:=1

to n do

read(a[i]);

for i:=1

to n do

begin

zz[i]:=i-1;

yy[i]:=i+1;

end;

fillchar(b,sizeof(b),false);

for i:=1

to n-1

do put(i,i+1);

repeat

while b[l[1]]or b[r[1]] do pop;

if l[1]1] then

write(l[1],' ',r[1],' ')

else

write(r[1],' ',l[1],' ');

b[r[1]]:=true; b[l[1]]:=true;

t1:=zz[l[1]];

t2:=yy[r[1]];

zz[t2]:=t1;

yy[t1]:=t2;

n:=n-2;

pop;

if (t1>0)and(t2<=nn) then

begin

put(t1,t2);

end;

until n<2;

close(input);

close(output);

end.

堆(大根堆 小根堆)

堆又可稱之為完全二叉堆。這是乙個邏輯上基於完全二叉樹 物理上一般基於線性資料結構 如陣列 向量 鍊錶等 的一種資料結構。學習過完全二叉樹的同學們都應該了解,完全二叉樹在物理上可以用線性資料結構進行表示 或者儲存 例如陣列int a 5 就可以用來描述乙個擁有5個結點的完全二叉樹。那麼基於完全二叉樹的...

堆(Heap)大根堆 小根堆

具有以下的特點 1 完全二叉樹 2 heap中儲存的值是偏序 min heap 父節點的值小於或等於子節點的值 max heap 父節點的值大於或等於子節點的值 一般都用陣列來表示堆,i結點的父結點下標就為 i 1 2。它的左右子結點下標分別為2 i 1和2 i 2。如第0個結點左右子結點下標分別為...

堆(Heap)大根堆 小根堆

目錄一般都用陣列來表示堆,i結點的父結點下標就為 i 1 2。它的左右子結點下標分別為2 i 1和2 i 2。如第0個結點左右子結點下標分別為1和2。插入乙個元素 新元素被加入到heap的末尾,然後更新樹以恢復堆的次序。每次插入都是將新資料放在陣列最後。可以發現從這個新資料的父結點到根結點必然為乙個...