您的位置:首页 > 理论基础 > 计算机网络

HDU 5884 青岛网络赛(二分加维护队列)

2016-09-17 21:15 330 查看


Sort

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 689    Accepted Submission(s): 134


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 (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

 
题目大意:
nn
个有序序列的归并排序.每次可以选择不超过
kk
个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过
TT
,
kk
最小是多少。
思路:先对所有的数排序,二分查找k,之后再将合并之后的数字存入一个队列之中。每次取数组和队列中较小的数。这样就可以,不过有个需要注意
如果
(n-1)
\%(k-1) \neq 0(n−1)%(k−1)≠0
,要把最小的
(n-1)\%(k-1)+1(n−1)%(k−1)+1
个数先合并一下
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
long long num[111111];
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
long long n,T;
queue<long long> q;
scanf("%lld%lld",&n,&T);
for (int i = 0 ; i < n ; i++ )
{
scanf("%lld",&num[i]);
}
sort(num,num+n);
while (!q.empty())
{
q.pop();
}
int l = 2 , r = n;
while (l <r)
{
long long sum = 0;
int mid = (l + r) / 2;
//printf("%d\n",mid);
long long temp = 0;
int all = 0;
if ((n - 1) % (mid - 1) != 0)
{
for (int i = 0 ; i < ((n - 1) % (mid - 1)) + 1 ; i++ )
{
temp += num[i];
}
all = ((n - 1) % (mid - 1)) + 1;
sum += temp;
q.push(temp);
}
temp = 0;
int cou = 0;
while (!q.empty() || all < n)
{
if (q.empty())
{
sum += num[all];
temp += num[all];
all++;
cou++;
}
else
{
if ( all < n)
{
if (q.front() >= num[all])
{
sum += num[all];
temp += num[all];
all++;
cou++;
}
else
{
sum += q.front();
temp += q.front();
q.pop();
cou++;
}
}
else
{
sum += q.front();
temp += q.front();
q.pop();
cou++;
}
}
if ( cou == mid )
{
if ( all < n || !q.empty())
q.push(temp);
else
break;
temp = 0;
cou = 0;
}
//printf("%lld %d\n",sum , all);
}
while (!q.empty())
{
q.pop();
}
if (sum > T)
{
l = mid + 1;
}
else
{
r = mid;
}
}
printf("%d\n",l);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分 队列