洛谷P2949 Work Scheduling G
[洛谷P2949 Work Scheduling G]([P2949 USACO09OPEN]Work Scheduling G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))
[USACO09OPEN]Work Scheduling G
题面翻译
约翰有太多的工作要做。为了让农场高效运转,他必须靠他的工作赚钱,每项工作花一个单位时间。 他的工作日从 \(0\) 时刻开始,有 \(10^9\) 个单位时间。在任一时刻,他都可以选择编号 \(1\) 到 \(N\) 的 \(N(1 \leq N \leq 10^5)\) 项工作中的任意一项工作来完成。 因为他在每个单位时间里只能做一个工作,而每项工作又有一个截止日期,所以他很难有时间完成所有N个工作,虽然还是有可能。 对于第 \(i\) 个工作,有一个截止时间 \(D_i(1 \leq D_i \leq 10^9)\),如果他可以完成这个工作,那么他可以获利 \(P_i( 1\leq P_i\leq 10^9 )\). 在给定的工作利润和截止时间下,约翰能够获得的利润最大为多少.
输入格式
* Line 1: A single integer: N
* Lines 2..N+1: Line i+1 contains two space-separated integers: D_i and P_i
输出格式
* Line 1: A single number on a line by itself that is the maximum possible profit FJ can earn.
样例 #1
样例输入 #1
3 2 10 1 5 1 7
样例输出 #1
17
提示
Complete job 3 (1,7) at time 1 and complete job 1 (2,10) at time 2 to maximize the earnings (7 + 10 -> 17).
题解:
反悔贪心。首先按照日期升序排列,因为我们一般印象就是截止日期早的先做嘛,这没有问题,但是如果说我们后面遇到了截止日期虽然晚,但是利润高的,例如
1 5
1 7
2 10
2 15
我们发现截止日期为2的利润为15的明显比1,7更优,但是1,7和2,10我们都已经做了,那我们怎么办?就是说第二个单位时间我们已经用了,所以说我们反悔即可
我们利用优先队列维护利润获得最小值,q.size()代表已经过了多少个单位时间,这样我们如果一份任务的截止日期d>q.size(),说明截止日期还没到,我们直接做,不犹豫,如果截止日期d<=q.size(),说明你这个任务已经到了截止时间,但是我可以反悔让你在还没截止的时候做,等于让之前的一个任务不去做了,很经典的反悔贪心,直接看代码
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define all(x) (x).begin(), (x).end()
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e5 + 10;
priority_queue<ll, vector<ll>, greater<ll>> q;
pll a[N];
int main(void)
{
Zeoy;
int t = 1;
// cin >> t;
while (t--)
{
int n;
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i].first >> a[i].second;
sort(a + 1, a + 1 + n);
ll sum = 0;
for (int i = 1; i <= n; ++i)
{
if (a[i].first > q.size())
{
sum += a[i].second;
q.push(a[i].second);
}
else
{
if (q.size() && a[i].second > q.top())
{
sum -= q.top();
q.pop();
sum += a[i].second;
q.push(a[i].second);
}
}
}
cout << sum << endl;
}
return 0;
}