题目描述
有n个人在m个窗口打饭,因为每个人的需求不同,所以每个人的“窗口占用时间”也不同。第i个人的窗口占用时间为 t i t_i ti。
请问如何安排这些人到窗口打饭,可以使得所有人等待的时间之和最小?
输入格式
第一行两个整数n,m。 ( 1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ m ≤ 2 × 1 0 5 ) (1 \leq n \leq 2 \times 10^5, 1 \leq m \leq 2 \times 10^5) (1≤n≤2×105,1≤m≤2×105)
接下来一行,n个整数表示 t i t_i ti。 ( 1 ≤ t i ≤ 1 0 9 ) (1 \leq t_i \leq 10^9) (1≤ti≤109)
输出格式
一个整数表示答案。
样例
输入1
5 3
3 2 1 5 7
输出1
3
解释: ( 1 , 5 ) , ( 2 , 7 ) , ( 3 ) (1,5),(2,7),(3) (1,5),(2,7),(3),这样安排可以使得每个人的等待时间之和最小,为3。
思路
这是一个最小延迟调度问题。目标是找到一种方法,将n个人分配到m个窗口,使得所有人的等待时间之和最小。每个人的窗口占用时间已知。
使用两个优先队列,pq1和pq2。pq1用于存储所有人的窗口占用时间,pq2用于存储每个窗口的总等待时间。首先,所有人的窗口占用时间被读入pq1,m个窗口的初始等待时间(都为0)被读入pq2。
在每一步,都选择将当前等待时间最短的窗口分配给下一个人。进入一个循环,直到所有人都被分配到窗口为止。在每一步,从pq1中取出一个人,从pq2中取出当前等待时间最短的窗口,将这个人分配到这个窗口上,然后更新这个窗口的总等待时间,并将其重新插入pq2。同时,这个窗口的等待时间被加入到总等待时间ans中。
当所有人都被分配到窗口后,总等待时间ans就是要求的答案。这个答案代表了所有人的等待时间之和的最小值。
AC代码
#include <algorithm>
#include <iostream>
#include <queue>
#define AUTHOR "HEX9CF"
#define ll long long
using namespace std;int n, m;
ll ans;
priority_queue<int, vector<int>, greater<int>> pq1, pq2;int main() {cin >> n >> m;for (int i = 1; i <= n; i++) {int t;cin >> t;pq1.push(t);}for (int i = 1; i <= m; i++) {pq2.push(0);}ans = 0;while (pq1.size()) {// cout << pq1.top() << " " << pq2.top() << endl;ans += pq2.top();pq2.push(pq2.top() + pq1.top());pq1.pop();pq2.pop();}cout << ans << endl;return 0;
}