hdu5884 Sort

//---------------------------------------------------------------
/*---贪心策略+二分+队列
-----将原数组排序,然后每次取k个较小的数合并,将合并的结果保存在一个队列中,继续取出k个数(队列和数组中)...
-----但是会出现一个问题当(n-1)%(k-1)!=0时,这样最后剩下的数个数小于k,这会导致序列非严格递减。于是可以先将
-----前(n-1)%(k-1)+1个数合并结果放入队列中,剩下的恰好可以每次合并k个数
*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<queue>
#include<algorithm>
#include<string.h>
typedef long long LL;
using namespace std;

const int maxn = 100000 + 5;
int a[maxn];
int n, T;

bool findK(int k){
	queue<LL>q;
	LL ans = 0, s = 0;
	int r = (n - 1) % (k - 1),p=0;
	if (r){
		while (p < r + 1) s += a[p++];

		ans += s;
		q.push(s);
	}
	while (true){
		s = 0;
		for (int i = 0; i < k; i++){
			if (p < n && (q.empty() || a[p] < q.front())) s += a[p++];
			else{
				s += q.front();
				q.pop();
			}
		}
		ans += s;
		if (ans>T)return false;
		if (p >= n&&q.empty())break;
		q.push(s);
	}
	return ans <= T;
}

int search(int l, int r){
	while (l < r){
		int k = (l + r) >> 1;
		if (findK(k))
			r = k;
		else l = k + 1;
	}
	return r;
}

int main(){
	int t;
	scanf("%d", &t);
	while (t--){
		scanf("%d%d", &n, &T);
		for (int i = 0; i < n; i++)scanf("%d", &a[i]);

		sort(a, a + n);  //排序
		printf("%d\n", search(2, n));
	}
	return 0;
}

  

posted @ 2016-09-19 12:31  曹孟德  阅读(394)  评论(0编辑  收藏  举报