3377 接水问题2 优先队列的使用
2015-05-24 11:29
337 查看
题目链接 http://codevs.cn/problem/3377/
题目描述 Description
学校里有一个水房,水房里一共装有m个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为1。
现在有n名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从 1到n编号,i号同学的接水量为wi。接水开始时,1到m号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学j完成其接水量要求wj后,下一名排队等候接水的同学k马上接替j同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即j同学第x秒结束时完成接水,则k同学第x+1秒立刻开始接水。若当前接水人数n’不足m,则只有n’个龙头供水,其它m-n’个龙头关闭。
现在给出n名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。
另外,同学们将会莫名其妙地排好了队,接水所用时间更长的先接。
输入描述 Input Description
第 1 行2 个整数 n 和 m,用一个空格隔开,分别表示接水人数和龙头个数。
第 2 行 n 个整数 w1、w2、„„、wn,每两个整数之间用一个空格隔开,wi表示 i 号同学的接水量。
输出描述 Output Description
输出只有一行,1 个整数,表示接水所需的总时间。
样例输入 Sample Input
5 3
4 4 1 2 1
样例输出 Sample Output
4
数据范围及提示 Data Size & Hint
【输入输出解释】
第 1 秒,3 人接水。第 1秒结束时,1、2、3 号同学每人的已接水量为 1,3 号同学接完水,4 号同学接替 3 号同学开始接水。
第 2 秒,3 人接水。第 2 秒结束时,1、2 号同学每人的已接水量为 2,4 号同学的已接水量为 1。
第 3 秒,3 人接水。第 3 秒结束时,1、2 号同学每人的已接水量为 3,4 号同学的已接水量为 2。4号同学接完水,5 号同学接替 4 号同学开始接水。
第 4 秒,3 人接水。第 4 秒结束时,1、2 号同学每人的已接水量为 4,5 号同学的已接水量为 1。1、2、5 号同学接完水,即所有人完成接水。
【数据范围】
对于 30%的数据,n≤10,000,m≤1,000;
对于全部的数据,1≤m≤n≤1,000,000,1≤m≤100,000。
思路:首先如果按【输入输出解释】中的描述必定会被坑一次。重点是题目描述中最后一句话---
另外,同学们将会莫名其妙地排好了队,接水所用时间更长的先接。
参照这个规则确定接水顺序即可
如下图所示例如有m个龙头,- 表示时间线。
1 --------
2-------------------------
3----------
,
,
m-----------------
如果某个龙头没人接水了,按照所用时间,最长时间的补上去,继续接,那么有序各个龙头接水在时间上存在重叠,显然最后所用的时间是某个龙头上最长的接水时间。
这样建立一个小根堆,一个大根堆,每次将大根堆顶元素取出,然后再取出小根堆顶元素,二者相加,将结果加入小根堆。这表示第一个接完水的人离开后,用时最大的补上去,这个龙头当前的总耗时。 最后当大根堆为空时,找出小根堆的最大值就是最终的结果。
代码
题目描述 Description
学校里有一个水房,水房里一共装有m个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为1。
现在有n名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从 1到n编号,i号同学的接水量为wi。接水开始时,1到m号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学j完成其接水量要求wj后,下一名排队等候接水的同学k马上接替j同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即j同学第x秒结束时完成接水,则k同学第x+1秒立刻开始接水。若当前接水人数n’不足m,则只有n’个龙头供水,其它m-n’个龙头关闭。
现在给出n名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。
另外,同学们将会莫名其妙地排好了队,接水所用时间更长的先接。
输入描述 Input Description
第 1 行2 个整数 n 和 m,用一个空格隔开,分别表示接水人数和龙头个数。
第 2 行 n 个整数 w1、w2、„„、wn,每两个整数之间用一个空格隔开,wi表示 i 号同学的接水量。
输出描述 Output Description
输出只有一行,1 个整数,表示接水所需的总时间。
样例输入 Sample Input
5 3
4 4 1 2 1
样例输出 Sample Output
4
数据范围及提示 Data Size & Hint
【输入输出解释】
第 1 秒,3 人接水。第 1秒结束时,1、2、3 号同学每人的已接水量为 1,3 号同学接完水,4 号同学接替 3 号同学开始接水。
第 2 秒,3 人接水。第 2 秒结束时,1、2 号同学每人的已接水量为 2,4 号同学的已接水量为 1。
第 3 秒,3 人接水。第 3 秒结束时,1、2 号同学每人的已接水量为 3,4 号同学的已接水量为 2。4号同学接完水,5 号同学接替 4 号同学开始接水。
第 4 秒,3 人接水。第 4 秒结束时,1、2 号同学每人的已接水量为 4,5 号同学的已接水量为 1。1、2、5 号同学接完水,即所有人完成接水。
【数据范围】
对于 30%的数据,n≤10,000,m≤1,000;
对于全部的数据,1≤m≤n≤1,000,000,1≤m≤100,000。
思路:首先如果按【输入输出解释】中的描述必定会被坑一次。重点是题目描述中最后一句话---
另外,同学们将会莫名其妙地排好了队,接水所用时间更长的先接。
参照这个规则确定接水顺序即可
如下图所示例如有m个龙头,- 表示时间线。
1 --------
2-------------------------
3----------
,
,
m-----------------
如果某个龙头没人接水了,按照所用时间,最长时间的补上去,继续接,那么有序各个龙头接水在时间上存在重叠,显然最后所用的时间是某个龙头上最长的接水时间。
这样建立一个小根堆,一个大根堆,每次将大根堆顶元素取出,然后再取出小根堆顶元素,二者相加,将结果加入小根堆。这表示第一个接完水的人离开后,用时最大的补上去,这个龙头当前的总耗时。 最后当大根堆为空时,找出小根堆的最大值就是最终的结果。
代码
#include <iostream> #include <queue> #include <cstdio> using namespace std; int n,m,pi; priority_queue<int,vector<int>,greater<int> > pr; // 小顶堆 priority_queue<int> bpr; // 一个大顶堆 int main(int args, char** argv) { scanf("%d%d",&n,&m); int maxv = 0; // 保存最大时间 for (;n > 0;) { scanf("%d",&pi); bpr.push(pi); n = n - 1; } while (!bpr.empty()) // 后被队列中还有元素 { int v = bpr.top(); // 前m个排队的人中,最大的。 if (pr.size() < m) { if (v > maxv) maxv = v; pr.push(v); // 第i个人接水,压入队列 } else { int water = pr.top() + v; if (water > maxv) maxv = water; pr.pop(); pr.push(water); } bpr.pop(); } printf("%d",maxv); }
相关文章推荐
- HDU 1026 迷宫战斗问题 使用了优先队列
- POJ 1724 ROADS(使用邻接表和优先队列的BFS求解最短路问题)
- c++优先队列使用结构体
- 优先队列PriorityQueue实现 大小根堆 解决top k 问题
- c++STL中优先队列的使用
- PAT 甲级 1003. Emergency 使用 优先队列 dijkstra 算法
- CF916B Jamie and Binary Sequence 二进制转化问题 字典序用优先队列来维护
- 哈理工OJ1621_迷宫问题II【BFS+优先队列】
- 工作队列使用碰到的问题
- c++优先队列的使用
- C++ STL中的优先队列(priority_queue)使用
- 如约而至,Java 10 正式发布! Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势 努力的孩子运气不会太差,跌宕的人生定当更加精彩 优先队列详解(转载)
- 优先队列的多路归并问题
- Python之队列queue模块使用 常见问题与用法
- 倒水问题<隐式图遍历><结构体中帮设置优先队列>
- RabbitMQ使用不当导致的队列堵塞问题及解决之道
- 数据结构之广度优先搜索(队列实现)问题
- 用“双优先队列”方法解决双/多指标的规划问题
- C++ 优先队列的基本使用方法
- javaWeb 使用线程池+队列解决"订单并发"问题