題目如下:
描述
定義一個數組,初始化爲空。在數組上執行兩種操作:
1、增添1個元素,把1個新的元素放入數組。
2、輸出並刪除數組中最小的數。
使用堆結構實現上述功能的高效算法。
對於每組測試數據,第一行輸入一個整數n,代表操作的次數。
每次操作首先輸入一個整數type。
當type=1,增添操作,接着輸入一個整數u,代表要插入的元素。
當type=2,輸出刪除操作,輸出並刪除數組中最小的元素。
1<=n<=100000。輸出每次刪除操作輸出被刪除的數字。樣例輸入
2 5 1 1 1 2 1 3 2 2 4 1 5 1 1 1 7 2樣例輸出
1 2 1提示每組測試數據的複雜度爲O(nlgn)的算法才能通過本次,否則會返回TLE(超時)
需要使用最小堆結構來實現本題的算法
以前寫樹的代碼時一直用的鏈表形式,現在試了一下數組的寫法,感覺比較也比較好理解,寫法也比較簡單。代碼及註釋如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[100010];
int n;
//下標下移,在刪除後更新樹時需要用到
void down( int root )
{
int son = 2*root; //記錄根節點的左兒子
int t = a[root];
while( son <= n)
{
if( son <= n -1 && a[son] > a[son+1]) //防止數組越界,且記錄較小值兒子節點的下標
son++;
if( t > a[son]) //更新節點。
{
a[root] = a[son];
root = son;
son = 2*root;
}
else break;
}
a[root] = t;
}
//數組下標上移,插入節點時用到。
void up( int son )
{
int t = a[son];
int tson = son;
while( (tson > 1)&&( a[tson/2] > t)) //更新節點。
{
a[tson] = a[tson/2];
tson = tson/2;
}
a[tson] = t;
}
void charu( int t)
{
a[ ++n ] = t;
up( n );
}
void del( )
{
if(n==0)
return ;
cout << a[1] << endl; //根節點肯定是最小值。
a[1] = a[n--];
down( 1 );
}
int main()
{
int t;
scanf("%d",&t);
while( t-- )
{
n = 0;
int type;
int m;
scanf("%d",&m);
for(int i = 0; i< m; i++)
{
scanf("%d",&type);
if(type == 1)
{
int b;
scanf("%d",&b);
charu( b ) ;
}
else
{
del();
}
}
}
return 0;
}