题目连接:https://cn.vjudge.net/problem/HDU-5884
题意:给你n个序列,将其合并为一个,每次合并的花费为合并序列的长度的加和,先给你总花费T,保证在花费不超过T的基础上,求每次最少需要合并几个序列。
做题的时候虽然只是想到了二分+哈夫曼树,可是由于数组开小了,导致一直wa,最后发现了,改掉数组之后,立马超时
哈哈哈,果然纯2分+优先队列是不行的 需要优化。
两个数组模拟优先队列也行,
下面这样做也行
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define ll long long
#define pb push_back
using namespace std;
const int MAXM = 100100;
const int INF = 0x3f3f3f3f;
int T, n;
ll a[MAXM],m, sum[MAXM];
priority_queue<ll,vector<ll>, greater<ll> >q;
bool f(int x) {
while(!q.empty())q.pop();
ll ans=0,cnt=0,temp=0;
int r = (n-1)%(x-1);
if(r) {
r++;
q.push(sum[r]);
ans+=q.top();
}
for(int i=r+1;i<=n;i++) q.push(a[i]);
cnt = (n - 1) / (x - 1);
while(cnt--) {
temp = 0;
int k = x;
while(k--) {
temp+=q.top();
q.pop();
}
ans+=temp;
q.push(temp);
if(ans>m)return 0;
}
return ans<=m;
}
int main()
{
scanf("%d",&T);
while(T--) {
sum[0] = 0;
scanf("%d%lld", &n, &m);
for(int i = 1;i <= n; i++) {
scanf("%lld", &a[i]);
}
sort(a+1, a+n+1);
for(int i=1;i<=n;i++)
sum[i] = sum[i - 1] + a[i];
int l = 2, r = n;
while(l<=r) {
int mid = l + r >> 1;
if(f(mid))
r = mid - 1;
else l = mid + 1;
}
printf("%d\n",l);
}
return 0;
}