1. 程式人生 > >Sort 【HDU - 5884】【哈夫曼樹】

Sort 【HDU - 5884】【哈夫曼樹】

題目連結


  一開始看到題的時候,竟然讀成了是按照升序排序的一串數,害得我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;
}