# Priority Queue# Greedy# Simulation

f631 - 同學會

🔗 前往 ZeroJudge 原題

題目描述

題目描述了一個同學會的用餐情境。已知 N 位同學的初始金額,以及 M 道菜的價格。每道菜由當時最富有同學支付,如果最富有同學的金額不足,則由依次較富有的同學補足。如果所有同學的總金額不足支付所有菜餚,則輸出 "Oh My God"。題目要求輸出最初最富有同學的金額,以及用餐結束後最富有同學的金額。

解題思路

本題可以使用優先佇列 (priority queue) 來模擬同學的財產狀況。優先佇列按照同學的財產從大到小排列。對於每一道菜,從優先佇列中取出最富有同學的財產,如果該同學的財產足夠支付菜餚費用,則扣除費用後將剩餘財產放回優先佇列。否則,將該同學的財產設為 0 並放回優先佇列,然後繼續從優先佇列中取出下一位同學的財產,直到支付完菜餚費用或所有同學的財產都用完。如果在支付過程中發現所有同學的財產總和不足支付菜餚費用,則輸出 "Oh My God"。最後,輸出最初最富有同學的金額和用餐結束後最富有同學的金額。

複雜度分析

  • 時間複雜度: O(N log N + M log N)
  • 空間複雜度: O(N)

程式碼

#include <iostream>
#include <queue>
using namespace std;
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	int n,m,t;
	while(cin >> n >> m){
		priority_queue <int> a;
		int mn=0,s=0;
		for(int i=0;i<n;++i){
			cin >> t;
			a.push(t);
		}
		mn=a.top();
		while(m--){
			cin >> t;
			while(t&&!s){
				if(a.top()>=t){
					int tmp=a.top()-t;
					t=0;
					a.pop();
					a.push(tmp);
				}
				else{
					t-=a.top();
					a.pop();
					a.push(0);
				}
				if(a.top()==0&&t)
					s=1;
			}
		}
		if(s)
			cout << "Oh My God\n";
		else
			cout << mn << " " << a.top() << "\n";
	}
}

Discussion