二分 + 曼哈夫优化
这题时间卡的比较紧,nlogn能过,大部分二分+优先队列或者写的不好的曼哈夫都TLE了
有人表示用nlognlogn 卡一下输入也过了。。
二分一下k,当k确定的时候,每次取前k个数判断一下是否满足
哈夫曼用两个数组可以优化到 n 时间,总时间就是nlogn
#include<stdio.h>
#include<iostream>
#include<memory.h>
#include<stdlib.h>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<algorithm>
using namespace std;
const int MAXN = 100005;
const int INF = 0x3f3f3f3f;
typedef long long LL;
int T, N, M;
int a[MAXN], b[MAXN];
bool Check(int k)
{
int ai, bi, blen;
blen = 0;
ai = bi = 0;
int cost = 0;
bool first = true;
while (N - ai + blen - bi > 1)
{
int num = 0;
if (first)
{
if ((N - k) % (k - 1) == 0)
{
num = k;
}
else
{
num = (N - k) % (k - 1) + 1;
}
first = false;
}
else
{
num = k;
}
int sum = 0;
while (num--)
{
if (ai == N)
{
sum += b[bi];
bi++;
}
else if (bi == blen)
{
sum += a[ai];
ai++;
}
else if (a[ai] < b[bi])
{
sum += a[ai];
ai++;
}
else
{
sum += b[bi];
bi++;
}
}
cost += sum;
if (cost > M)
{
return false;
}
b[blen++] = sum;
}
return cost <= M;
}
int main() {
int T;
scanf("%d", &T);
{
int i;
for (int ca = 1; ca <= T; ca++)
{
scanf("%d%d", &N, &M);
for (i = 0; i < N; i++)
{
scanf("%d", &a[i]);
}
sort(a, a + N);
int head = 2;
int tail = N;
int mid, res;
while (head <= tail)
{
mid = (head + tail) / 2;
if (Check(mid))
{
res = mid;
tail = mid - 1;
}
else
{
head = mid + 1;
}
}
printf("%d\n", res);
}
}
return 0;
}