Problem Description
Recently, Bob has just learnt a naive sorting algorithm: merge sort. Now, Bob receives a task from Alice.
Alice will give Bob N sorted sequences, and the i -th sequence includes ai elements. Bob need to merge all of these sequences. He can write a program, which can merge no more than k sequences in one time. The cost of a merging operation is the sum of the length of these sequences. Unfortunately, Alice allows this program to use no more than T cost. So Bob wants to know the smallest k to make the program complete in time.
Alice will give Bob N sorted sequences, and the i -th sequence includes ai elements. Bob need to merge all of these sequences. He can write a program, which can merge no more than k sequences in one time. The cost of a merging operation is the sum of the length of these sequences. Unfortunately, Alice allows this program to use no more than T cost. So Bob wants to know the smallest k to make the program complete in time.
Input
The first line of input contains an integer
t0
, the number of test cases.
t0
test cases follow.
For each test case, the first line consists two integers N (2≤N≤100000) and T (∑Ni=1ai<T<231) .
In the next line there are N integers a1,a2,a3,...,aN(∀i,0≤ai≤1000) .
For each test case, the first line consists two integers N (2≤N≤100000) and T (∑Ni=1ai<T<231) .
In the next line there are N integers a1,a2,a3,...,aN(∀i,0≤ai≤1000) .
Output
For each test cases, output the smallest
k
.
Sample Input
1 5 25 1 2 3 4 5
Sample Output
3
对于二叉哈夫曼树,每次只需取两个最小的合并,再将合并的点放回队列,重复操作就ok了。
而k叉哈夫曼树,每次选择k个权值最小的点容易让最后一次合并的时候的点不足k个。分析:
每次删除k个点又加入1个点可知每次删除了k-1个点,而最后剩余1个点,可知总共删了n-1个点,
所以为保证每次都有k个点可选,那么(n-1)%(k-1)==0。
如果(n-1)%(k-1)!=0,,那么就要再放入(k-1-(n-1)%(k-1))个权值为0的虚拟点,
这样就保证每次都有k个点可选。
二分答案+优先队列时间复杂度n*log*log,利用合并的非递减性,设置两个queue,一个为原本的队列,
另一个用来放合并后的值,每次只需从这两个队列头取最小值就ok了,时间复杂度n*log。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int a[maxn];
queue<ll> que;
queue<ll> q;
inline ll sol(){
if(que.size()&&q.size()){
if(que.front()<q.front()){
ll t=que.front();
que.pop();
return t;
}
else {
ll t=q.front();
q.pop();
return t;
}
}
if(!que.empty()){
ll t=que.front();
que.pop();
return t;
}
else{
ll t=q.front();
q.pop();
return t;
}
}
int main(){
int t;scanf("%d",&t);
while(t--){
int n;ll T;
scanf("%d %I64d",&n,&T);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);
int l=2,r=n;
while(r-l>=1){
int mid=l+r>>1;
int cnt=0;
if((n-1)%(mid-1)!=0)cnt=(mid-1-(n-1)%(mid-1));
while(!q.empty())q.pop();
while(!que.empty())que.pop();
for(int i=0;i<cnt;i++)que.push(0);
for(int i=0;i<n;i++){
que.push(a[i]);
}
ll ans=0;
while(que.size()+q.size()>1){
ll sum=0;
for(int i=0;i<mid;i++){
ll tmp=sol();
sum+=tmp;
}
ans+=sum;
q.push(sum);
}
if(ans<=T)r=mid;
else l=mid+1;
}
printf("%d\n",r);
}
return 0;
}