题目
Sort
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2866 Accepted Submission(s): 719
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
题目大意
给你一组数(无序的),ai代表有ai个元素,要求我们把这些数合并成一个数,每次合并的数量是固定的,每次合并的花费你合并的数的和,例如你合并ai,aj,就就要花费SUM(ai+aj),但是你总的花费不能超过T,Bob想知道每次合并的数量最少是几?
解题思路
刚开始直接从1开始找,发现傻了点,这样的题,最适合二分,每次二分K,然后比较一下K叉哈夫曼树和T就可以啦,哈夫曼树不会的建议好好学习一下数据结构。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn =100000+10;
LL a[maxn];//存数的数组
LL b[maxn];//存加和的数组
int N;
int Hafuman(int k) //返回总代价,O(2*n)
{
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;
LL T;
scanf("%d",&t);
while(t--)
{
scanf("%d%lld",&N,&T);
for(int i=0;i<N;i++)
scanf("%lld",a+i);
sort(a,a+N);
int l=2,r=N;
while(l<r)
{
int mid=(l+r)>>1;
if(Hafuman(mid)<=T)
{
r=mid;
}
else
{
l=mid+1;
}
}
printf("%d\n",r);
}
return 0;
}