用二分法寻找K,再用O(n)时间的K叉哈弗曼树算法求K是否符合要求
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N],b[N],n;
ll t;
ll Hafuman(int k) //返回总代价
{
int ai, bi, blen;
blen = 0;
ai = bi = 0;
ll 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;
ll 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;
b[blen++] = sum;
}
return cost;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&t);
for(int i=0;i<n;i++)
scanf("%lld",&a[i]);
sort(a,a+n);
int l=2,r=n;
int ans=n;
while(l<r)
{
int m=(l+r)>>1;
if(Hafuman(m)<=t) ans=m,r=m;
else l=m+1;
}
printf("%d\n",ans);
}
return 0;
}