码迷,mamicode.com
首页 > 其他好文 > 详细

Sort HDU - 5884 哈夫曼权值O(n)

时间:2017-08-23 20:10:05      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:--   排序   合并   编码   blog   sed   bit   show   技术分享   

http://acm.hdu.edu.cn/showproblem.php?pid=5884

原来求一次哈夫曼可以有O(n)的做法。

具体是,用两个队列,一个保存原数组,一个保存k个节点合并的数值,然后每次选k个的时候,用two point在两个队列中选k个出来即可。

然后又把新的节点放去第二个队列那里去。

所以,首先需要排序(这样就和求 一次huffman编码的时间复杂度一样了nlogn)

然后这样明显第二个队列是单调递增的。

技术分享
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 100000 + 20;
int a[maxn];
int n, T;
LL que[2][maxn], head[2], tail[2];
LL en = 1e14;
bool check(int val) {
    head[0] = tail[0] = head[1] = tail[1] = 0;
    int res = n % (val - 1);
    if (res == 0) {
        res = val - 1;
    }
    LL ans = 0;
    if (res == 1) {
        for (int i = 1; i <= n; ++i) que[0][tail[0]++] = a[i];
    } else {
        int sum = 0;
        for (int i = 1; i <= res; ++i) sum += a[i];
        for (int i = res + 1; i <= n; ++i) que[0][tail[0]++] = a[i];
        ans = sum;
        que[1][tail[1]++] = sum;
    }
    while (true) {
        if (ans > T) return false;
        LL sum = 0;
        int want = val;
        while (want--) {
            LL mi1 = 1e14, mi2 = 1e14;
            if (head[0] < tail[0]) mi1 = que[0][head[0]];
            if (head[1] < tail[1]) mi2 = que[1][head[1]];
            if (mi1 < mi2) sum += mi1, head[0]++;
            else sum += mi2, head[1]++;
            if (mi1 == en && mi2 == en) return true; // 不可以取了
        }
        que[1][tail[1]++] = sum;
        ans += sum;
    }
    return true;
}
void work() {
    scanf("%d%d", &n, &T);
    for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    sort(a + 1, a + 1 + n);
    int be = 2, en = n;
//    cout << check(2) << endl;
    while (be <= en) {
        int mid = (be + en) >> 1;
        if (check(mid)) en = mid - 1;
        else be = mid + 1;
    }
    printf("%d\n", be);
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    int t;
    scanf("%d", &t);
    while (t--) work();
    return 0;
}
View Code

 

Sort HDU - 5884 哈夫曼权值O(n)

标签:--   排序   合并   编码   blog   sed   bit   show   技术分享   

原文地址:http://www.cnblogs.com/liuweimingcprogram/p/7419611.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!