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;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值