hdu5884 Sort(二分)

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 547    Accepted Submission(s): 101


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.
 

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 (2N100000) and T (Ni=1ai<T<231).
In the next line there are N integers a1,a2,a3,...,aN(i,0ai1000).
 

Output
For each test cases, output the smallest k.
 

Sample Input
1 5 25 1 2 3 4 5
 

Sample Output

3

题意:给你n个数,以及花费m,要你找到最小的k,每次你可以把至多k个数合并成一个数,每次这样操作的花费是这些数的总和,要使得最后合成一个数后的代价不超过m。

思路:先对整个a[]排序,二分k,然后用两个数组,第一个数组保存原来的a[]数组,第二个数组保存合并后的数,每次合并一个数后添加到这个数组的末位,每次取k个数是依次比较两个数组的头元素的大小,小的取出,直到取到k个数。这里要注意要先在a[]数组前补0,直到n补后%(k-1)==0.

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
#define lson th<<1
#define rson th<<1|1
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define Key_value ch[ch[root][1]][0]
#define MOD 1000003
#define maxn 100050
int a[maxn],b[maxn];
int n,m;
int cal(int k)
{
    int f2=1,r2=0,i;
    int f1,r1;
    int t=n%(k-1);
    int sum=0;
    for(i=1;i<=t;i++){
        sum+=a[i];
    }
    r2++;b[r2]=sum;
    r1=n;f1=t+1;

    int num=n/(k-1);
    int zong=sum;
    while(num--)
    {
        sum=0;
        for(i=1;i<=k;i++){
            if(f1>r1){
                sum+=b[f2];
                f2++;
            }
            else if(f2>r2){
                sum+=a[f1];
                f1++;
            }
            else{
                if(a[f1]<b[f2]){
                    sum+=a[f1];
                    f1++;
                }
                else{
                    sum+=b[f2];
                    f2++;
                }
            }
        }
        zong+=sum;
        if(zong>m)return 0;
        r2++;b[r2]=sum;
    }
    return zong<=m;
}



int main()
{
    int i,j,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+1+n);
        int l,r,mid;
        l=2;r=n;
        while(l<=r){
            mid=(l+r)/2;
            if(cal(mid))r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",l);
    }
    return 0;
}


展开阅读全文
©️2020 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值