Sort 【HDU - 5884】【哈夫曼樹】
阿新 • • 發佈:2018-12-09
題目連結
一開始看到題的時候,竟然讀成了是按照升序排序的一串數,害得我WA了兩發,還以為是補0補錯了,研究了一會補0發現好像沒有多大問題,然後就繼續了,直到再看了遍題,發現好像是沒有給你拍好序的,然後AC……
這道題其實哈夫曼樹不難,就是補0思想挺好的,遇到一串數字,我們要對它建立哈夫曼樹,我們總不能做到最後才補0吧,就得早些把0給放進去,這樣子基數小,才能建立最小的哈夫曼樹,那麼得放多少個0呢?我們假如要建立一棵X叉的哈夫曼樹,那麼每次的葉子節點就要有X個節點才行,假如,我們拿出一個節點,剩餘就是(N-1)個節點,這剩餘的(N-1)個節點必須是(X-1)的整數倍才能構成一棵完全的X叉樹,因為,我們對於每個(X-1)個節點都能加上之前取出來的“1”合併成一個新的“1”節點,然後繼續合併,最終合併成一個節點,所以(N-1)%(X-1)所多出來的節點 就是多出來的節點,我們要補上X-1-多出來的節點才行,這些就都是“0”節點來補了。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef unsigned long long ull; typedef long long ll; const ll INF = (ll)1<<61; const int maxN = 100005; int N; ll K; ll a[maxN]; bool check(int x) { queue<ll> Q1; queue<ll> Q2; for(int i=1; i<=x-((N-1)%(x-1))-1; i++) Q1.push(0); for(int i=1; i<=N; i++) Q1.push(a[i]); ll sum = 0; while(!Q1.empty() || !Q2.empty()) { int tmp = x; ll inque = 0; while(tmp--) { ll e1 = INF, e2 = INF; if(Q1.empty() && Q2.empty()) break; if(!Q1.empty()) e1 = Q1.front(); if(!Q2.empty()) e2 = Q2.front(); if(e1 <= e2) { sum += e1; inque += e1; Q1.pop(); } else { sum += e2; inque += e2; Q2.pop(); } } if(Q1.empty() && Q2.empty()) break; Q2.push(inque); } return sum<=K; } int solve(int L, int R) { int ans = N; int mid = (L + R)>>1; while(L<=R) { mid = (L + R)>>1; if(check(mid)) { ans = mid; R = mid - 1; } else L = mid + 1; } return ans; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d%lld", &N, &K); for(int i=1; i<=N; i++) scanf("%lld", &a[i]); sort(a+1, a+1+N); printf("%d\n", solve(2, N)); } return 0; }