水题
Time Limit: 500ms
Memory Limit: 32768KB
This problem will be judged on
HRBUST. Original ID:
2223
64-bit integer IO format: %lld Java class name: Main
因为是有关于接水的问题,便简称为水题了(。
N个人排队在M个出水口前接水,第i个人接水需时为t[i],
请问接水的最短用时是多少?
Input
第一行一个整数 T ,代表有 T 组数据。
每组数据
第一行两个整数 N(<=100000) , M(<=10000) 代表有 N 个人 M 个出水口。
第二行N个整数,第i个数字t[i](<=10000)代表第i个人接水用时t[i]。
Output
对于每组数据输出一个整数,代表
所需的最少接水时间
。
Sample Input
2
5 3
1 2 3 4 5
6 3
1 2 3 3 4 5
Sample Output
5
6
Hint
小桥流水哗啦啦,我和小岛去偷瓜
~
。
Source
解析:就是一个贪心思想,就像往一个瓶子里装核桃和沙子一样,怎么样才能在有限的空间里容纳更多重量,那就是先尽可能装最多大的,然后再处理小的,同样我们这题的思想也是,尽可能的先把最大的处理了,直到处理完为止。按从大到小的顺序处理,先加入m个最大的元素进入队首为最小元素的优先级队列,然后再不断从队首取出元素(队首为队列中的最小值),让它加上当前未加入的最大元素,再放入队列中,重复上述操作,直到把所有的n-m个全部加进去即可,此时队列中的最大值(也就是队尾元素),就是答案。
AC代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define INF 0x7fffffff
#define LL long long
#define MID(a, b) a+(b-a)/2
const int maxn = 1000 + 10;
#pragma comment(linker, "/STACK:1024000000,1024000000")
int a[100005];
int main(){
#ifdef sxk
freopen("in.txt", "r", stdin);
#endif // sxk
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int t, n, m;
scanf("%d", &t);
while(t--){
priority_queue<int, vector<int>, greater<int> > p; //最小值优先的优先级队列
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++) scanf("%d", &a[i]);
sort(a, a+n);
for(int i=n-1; i>=0; i--){
if(i >= n-m) p.push(a[i]); //先入队m个
else{
int x = p.top();
p.pop();
p.push(x + a[i]);
}
}
int ans;
while(p.size()){
ans = p.top();
p.pop();
}
printf("%d\n", ans) ;
}
return 0;
}