您的位置:首页 > 其它

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

2017-08-23 18:36 274 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: