題目描述
如題,初始小根堆為空,我們需要支援以下3種操作:
操作1: 1 x 表示將x插入到堆中
操作2: 2 輸出該小根堆內的最小數
操作3: 3 刪除該小根堆內的最小數
輸入輸出格式
輸入格式:
第一行包含乙個整數n,表示操作的個數
接下來n行,每行包含1個或2個正整數,表示三種操作,格式如下:
操作1: 1 x
操作2: 2
操作3: 3
輸出格式:
包含若干行正整數,每行依次對應乙個操作2的結果。
輸入輸出樣例
輸入樣例#1:
5 1 2
1 5
2 3
2輸出樣例#1:2 5
說明時空限制:1000ms,128m
資料規模:
對於30%的資料:n<=15
對於70%的資料:n<=10000
對於100%的資料:n<=1000000(注意是6個0。。。不過不要害怕,經過編者實測,堆是可以ac的)
樣例說明:
故輸出為2、5
題解託某位毒瘤張瀚文老師的福,學習了一大堆堆知識。
配對堆不像其他嬌氣的堆,它對堆本身的形態沒有什麼要求,只要是棵樹就行了,插入/合併也很任性,直接比較兩個根的大小,優先順序高的當爸爸,輕鬆o(
1)o (1
)完成插入/合併。
配對堆還可以支援改變堆中元素的值,只需要將元素原來的父邊斷掉,修改完權值後直接與根合併就完了,雖然看起來是o(
1)o (1
)的,但是因為會影響到po
p pop
操作,所以均攤下來複雜度為o(
log2
n)o (l
og2n
)。因為前面的操作比較隨意,所以po
p pop
操作要收拾隨意連邊的爛攤子,我們要把根節點的所有兒子不停地兩兩合併合成一棵樹,複雜度是o(
兒子個數
) o(兒
子個數)
的,但是神奇攤還分析說,它是o(
log2
n)o (l
og2n
)的,它就是o(
log2
n)o (l
og2n
)的。**賊好寫,甚至短於左偏樹。
#include
using
namespace
std;
const
int m=2e6+5;
int n,root,id,tot,top,val[m],head[m],nxt[m],to[m],dad[m];
queue
dui;
void add(int x,int y)
int _new(int x)
int merge(int x,int y)else }
void pop()
if(dui.size())root=dui.front(),dui.pop();
else root=0;
}void in()
void ac()
}int main()
配對堆 資料結構說解
乙個配對堆是一棵滿足堆序性質的樹,樹上每個節點儲存其關鍵字 子節點指標 兄弟節點指標和前驅指標。當該節點為其父節點的第乙個兒子,即父節點的子節點指標指向該節點時,該節點的前驅指標指向其父節點 否則該節點的前驅指標指向該節點的前乙個兄弟,即該節點的前驅指標指向的節點的兄弟節點指標指向該節點。配對堆可以...
資料結構 堆
最大堆 最小堆 堆的定義是 n個元素的序列,當且僅當滿足如下關係時被成為堆 1 ki k2i 且 ki k2i 1 或 2 ki k2i 且 ki k2i 1 i 1,2,n 2 當滿足 1 時,為最小堆,當滿足 2 時,為最大堆。若將此序列對應的一維陣列堪稱是乙個完全二叉樹,則2i和2i 1個節點...
資料結構 堆
資料結構 堆的操作和實現 當應用優先順序佇列或者進行堆排序時,一般利用堆來實現。堆是乙個完全 除最底層 外都是滿的 二叉樹,並滿足如下條件 1 根結點若有子樹,則子樹一定也是堆。2 根結點一定大於 或小於 子結點。因為要求堆必須是完全二叉樹,所以可以用線性的資料結構,比如陣列,來實現堆。利用陣列實現...