zoukankan      html  css  js  c++  java
  • Sort HDU5884(二分+多叉哈夫曼树)

    HDU5884 Sort

    题意:有n个序列要进行归并,每次归并的代价是两个序列的长度的和,要求最终的代价不能超过规定的T,求在此前提下一次能同时进行归并的序列的个数k。

    思路:还是太单纯,看完题目一直以为要用归并排序来解题,如果已经看过多叉哈夫曼树的知识的话估计就不会这样了。先二分查找这个k,然后用多叉哈夫曼树来判断这个k是不是还能再变小。用两个队列来实现多叉哈夫曼树。

    PS:如果不进行提前处理的话,最后一次的归并可能就凑不齐k个来了,所以需要提前处理一下。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <set>
    #include <queue>
    using namespace std;
    const int maxn = 1e5 + 100;
    typedef long long ll;
    //typedef pair<int,int> P;
    queue<ll> q1;
    queue<ll> q2;
    int T,n;
    ll a[maxn];
    ll t;
    
    bool Hufman(int x)
    {
        while (!q1.empty()) q1.pop();
        while (!q2.empty()) q2.pop();
        int tt = (n - 1) % (x - 1);
    
        if (tt)
        {
            for (int i = 1; i <= x - 1 - tt; i++)//添加虚构0,使得最后一次能凑齐k个序列,手动模拟了一下求tt的过程,
                q1.push(0);//但不明白n-1具体的原因,不知是不是固定的模式
        }
        for (int i = 1; i <= n; i++)
            q1.push(a[i]);
        ll sum = 0;
        while (1)
        {
            ll tem = 0;
            for (int i = 1; i <= x; i++)
            {
                if (q1.empty() && q2.empty())break;
                if (q1.empty())
                {
                    tem += q2.front();
                    q2.pop();
                }
                else if (q2.empty())
                {
                    tem += q1.front();
                    q1.pop();
                }
                else
                {
                    int tx, ty;
                    tx = q1.front();
                    ty = q2.front();
                    if (tx < ty)
                    {
                        tem += tx;
                        q1.pop();
                    }
                    else
                    {
                        tem += ty;
                        q2.pop();
                    }
                }
            }
            sum += tem;
            if (q1.empty() && q2.empty())break;
            q2.push(tem);//q2这个序列一定是有序的
        }
        if (sum <= t)
            return 1;
        else
            return 0;
    }
    
    int main()
    {
        scanf("%d", &T);
        while (T--)
        {
            scanf("%d%lld", &n, &t);
            for (int i = 1; i <= n; i++)
                scanf("%lld", &a[i]);
            sort(a + 1, a + 1 + n);
            
            int st = 2, en = n;
            
            while (st < en)
            {
                int mid = (st + en) / 2;
                if (Hufman(mid))
                    en = mid;
                else
                    st = mid + 1;
                //printf("GG
    ");
            }
            printf("%d
    ", st);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    sublime text 4 vim 插件配置
    ssh-keygen 的使用
    distribution transaction solution
    bilibili 大数据 视频下载 you-get
    Deepin 20.2.1 安装 MS SQL 2019 容器版本
    【转】使用Linux下Docker部署MSSQL并加载主机目录下的数据库
    【转】You Can Now Use OneDrive in Linux Natively Thanks to Insync
    dotnet 诊断工具安装命令
    Linux 使用 xrandr 设置屏幕分辨率
    【转】CentOS 7.9 2009 ISO 官方原版镜像下载
  • 原文地址:https://www.cnblogs.com/sykline/p/9737772.html
Copyright © 2011-2022 走看看