# Heap# Greedy# Data Structure

f498 - Heap

🔗 前往 ZeroJudge 原題

題目描述

題目要求實作一個 min heap 和一個 max heap,並以 level order 的方式輸出兩個 heap 的元素。輸入包含多組測試案例,每組案例先輸入一個整數 n,表示接下來有 n 個整數要插入 heap。然後輸入 n 個整數,這些整數將被分別插入 min heap 和 max heap。對於每組測試案例,程式需要輸出 min heap 和 max heap 的 level order 輸出。

解題思路

程式碼使用兩個陣列 ab 分別儲存 max heap 和 min heap。程式碼使用自底向上(bottom-up)的方式建構 heap。對於每個輸入數字,先將其插入 a (max heap) 和 b (min heap),然後從該數字的位置開始,向上比較並交換,直到滿足 heap 的性質。對於 max heap,如果當前節點的值大於其父節點的值,則交換它們。對於 min heap,如果當前節點的值小於其父節點的值,則交換它們。建構完 heap 之後,程式碼以 level order 的方式輸出 b (min heap) 和 a (max heap) 的元素。

複雜度分析

  • 時間複雜度: O(n log n) 建構 heap 的時間複雜度為 O(n log n),因為對於每個元素,我們最多需要向上移動 log n 層才能找到其正確位置。輸出 heap 的時間複雜度為 O(n)。因此,總時間複雜度為 O(n log n)。
  • 空間複雜度: O(n) 程式碼使用兩個大小為 n 的陣列 ab 儲存 heap,因此空間複雜度為 O(n)。

程式碼

#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define swap(x,y) { x = x + y; y = x - y; x = x - y; }
#include <stdio.h>
int a[1025],b[1025],n;
inline int read(){
	int a(0),f(1);
	char c('0');
	while(c>='0'||c=='-'){
		if(c=='-'){
			f=-1;
			c=getchar_unlocked();
		}
		a=(a<<3)+(a<<1)+c-'0';
		c=getchar_unlocked();
	}
	return a*f;
}
inline void write(int x) {
	if(x==0)
		putchar_unlocked('0');
	else{
		int stk[9],*ptr(&stk[0]);
		while(x){*ptr=x%10;x/=10;++ptr;}
		while(--ptr>=(&stk[0])){putchar_unlocked(*ptr+'0');}
	}
}
int main(){
	while(n=read()){
		for(int i=1,tmp=1;i<=n;++i,tmp=i){
			a[i]=read();
			b[i]=a[i];
			while(tmp>>1){
				if(a[tmp]>a[tmp>>1])
					swap(a[tmp],a[tmp>>1]);
				if(b[tmp]<b[tmp/2])
					swap(b[tmp],b[tmp>>1]);
				tmp>>=1;
			}
		}
		for(int j=1;j<=n;++j){
			write(b[j]);
			putchar_unlocked(' ');
		}
		putchar_unlocked('\n');
		for(int j=1;j<=n;++j){
			write(a[j]);
			putchar_unlocked(' ');
		}
		putchar_unlocked('\n');
	}
}

Discussion