【資料圖】
數(shù)據(jù)結(jié)構(gòu)
堆
1.插入一個(gè)元素:h[++size] = x; up(size);2.求集合中當(dāng)前最小值:h[1];3.刪除最小值:h[1] = h[size]; size--; down(1);4.刪除任意一個(gè)元素:h[k] = h[size]; size--; up(k) or down(k);5.修改任意一個(gè)元素:h[k] = x; up(k) or down(k);
[NOIP2004 提高組] 合并果子 / [USACO06NOV] Fence Repair G
題目描述
在一個(gè)果園里,多多已經(jīng)將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。多多決定把所有的果子合成一堆。
每一次合并,多多可以把兩堆果子合并到一起,消耗的體力等于兩堆果子的重量之和。可以看出,所有的果子經(jīng)過 \(n-1\) 次合并之后, 就只剩下一堆了。多多在合并果子時(shí)總共消耗的體力等于每次合并所耗體力之和。
因?yàn)檫€要花大力氣把這些果子搬回家,所以多多在合并果子時(shí)要盡可能地節(jié)省體力。假定每個(gè)果子重量都為 \(1\) ,并且已知果子的種類 數(shù)和每種果子的數(shù)目,你的任務(wù)是設(shè)計(jì)出合并的次序方案,使多多耗費(fèi)的體力最少,并輸出這個(gè)最小的體力耗費(fèi)值。
例如有 \(3\) 種果子,數(shù)目依次為 \(1\) , \(2\) , \(9\) 。可以先將 \(1\) 、 \(2\) 堆合并,新堆數(shù)目為 \(3\) ,耗費(fèi)體力為 \(3\) 。接著,將新堆與原先的第三堆合并,又得到新的堆,數(shù)目為 \(12\) ,耗費(fèi)體力為 \(12\) 。所以多多總共耗費(fèi)體力 \(=3+12=15\) ??梢宰C明 \(15\) 為最小的體力耗費(fèi)值。
輸入格式
共兩行。第一行是一個(gè)整數(shù) \(n(1\leq n\leq 10000)\) ,表示果子的種類數(shù)。
第二行包含 \(n\) 個(gè)整數(shù),用空格分隔,第 \(i\) 個(gè)整數(shù) \(a_i(1\leq a_i\leq 20000)\) 是第 \(i\) 種果子的數(shù)目。
輸出格式
一個(gè)整數(shù),也就是最小的體力耗費(fèi)值。輸入數(shù)據(jù)保證這個(gè)值小于 \(2^{31}\) 。
樣例 #1
樣例輸入 #1
3 1 2 9
樣例輸出 #1
15
提示
對于 \(30\%\) 的數(shù)據(jù),保證有 \(n \le 1000\):
對于 \(50\%\) 的數(shù)據(jù),保證有 \(n \le 5000\);
對于全部的數(shù)據(jù),保證有 \(n \le 10000\)。
import java.util.Scanner;public class Main { static final int N = 10010; static int[] h = new int[N]; static int size, n; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); for(int i = 1; i <= n; i++){ h[i] = sc.nextInt(); } size = n; for(int i = n / 2; i > 0; i--) down(i); int ans = 0; for(int i = 0; i < n - 1; i++){ int a = h[1]; h[1] = h[size]; size--; down(1); int b = h[1]; h[1] = h[size]; size--; down(1); ans += (a + b); h[++size] = (a + b); up(size); } System.out.println(ans); } public static void up(int u){ while(u / 2 > 0 && h[u / 2] > h[u]){ swap(h, u / 2, u); u /= 2; } } public static void down(int u){ int t = u; if(2 * u <= size && h[2 * u] < h[t]) t = 2 * u; if(2 * u + 1 <= size && h[2 * u + 1] < h[t]) t = 2 * u + 1; if(t != u){ swap(h, t, u); down(t); } } public static void swap(int[] arr, int i, int j){ int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }}
標(biāo)簽: