# Greedy# Sorting# Prefix Sum# Priority Queue

g597 - 3. 生產線

🔗 前往 ZeroJudge 原題

題目描述

題目要求在有 $n$ 台機器和 $m$ 個工作的生產線上,找到最佳的機器排列順序,以最小化完成所有工作的總時間。每個工作需要在指定範圍 $[l_i, r_i]$ 的機器上生產 $w_i$ 單位資料,每台機器生產單位資料所需時間不同。

解題思路

本題的核心思路是利用貪心法和排序。首先,將工作按照起始位置排序。然後,遍歷機器,並使用優先佇列維護當前可用的機器。對於每個機器,將其加入優先佇列,並計算當前位置的總生產能力。接著,遍歷每個工作,並將其所需的生產量分配給生產能力最高的機器。最後,將機器的生產時間按照降序排列,並與工作的價值(生產量)配對,以最小化總時間。

具體步驟如下:

  1. 讀取輸入,包括機器數量 $n$、工作數量 $m$ 以及每個工作的工作範圍和生產量。
  2. 將工作按照起始位置 $l_i$ 排序。
  3. 遍歷機器,將每個機器加入優先佇列,優先佇列按照生產能力(時間)降序排列。
  4. 計算每個位置的總生產能力,使用前綴和儲存。
  5. 讀取每個機器的生產時間 $t_i$。
  6. 將機器的生產時間和總生產能力排序。
  7. 將機器的生產時間按照降序排列,並與工作的價值(生產量)配對,計算總時間。

複雜度分析

  • 時間複雜度: O(m log m + n log n + n log n) (排序工作和機器,以及優先佇列操作)
  • 空間複雜度: O(n + m) (儲存工作和機器的陣列,以及優先佇列)

程式碼

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
long n,m,v,ans,it,c[200005],b[200005];
pair <long ,pair <long,long> > a[200005];//begin,end,v
priority_queue <pair <long,long> > p;//end,begin,v
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i=0;i<m;++i){
		cin >> a[i].first >> a[i].second.first >> a[i].second.second;
	}
	sort(a,a+m);
	for(int i=1;i<=n;++i){
		while(it<m&&a[it].first<=i){
			v+=a[it].second.second;
			p.push({-a[it].second.first,a[it].second.second});
			++it;
		}
		c[i]=v;
		while(p.empty()==0&&-p.top().first==i){
			v-=p.top().second;
			p.pop();
		}
	}
	for(int i=1;i<=n;++i){
		cin >> b[i];
	}
	sort(b+1,b+n+1);
	sort(c+1,c+n+1);
	for(int i=n,j=1;i>=1;--i,++j){
		ans+=b[i]*c[j];
	}
	cout << ans;
}

Discussion