[USACO09OPEN]Work Scheduling 经典反悔贪心
题意
约翰有太多的工作要做。为了让农场高效运转,他必须靠他的工作赚钱,每项工作花一个单位时间。
他的工作日从 (0)时刻开始,有 (10^9)个单位时间。在任一时刻,他都可以选择编号 (1)到 (N) 的 (N)((1 leq N leq 10^5)) 项工作中的任意一项工作来完成。 因为他在每个单位时间里只能做一个工作,而每项工作又有一个截止日期,所以他很难有时间完成所有N个工作,虽然还是有可能。 对于第 (i)个工作,有一个截止时间 (D_i)((1leq D_i leq 10^9)),如果他可以完成这个工作,那么他可以获利 (P_i,(1 leq P_i leq 10^9))在给定的工作利润和截止时间下,约翰能够获得的利润最大为多少.
分析
限定的选择获得最大价值,我们肯定贪心地选择最大的价值。
对时间排序后,若该物品的价值比当前选的最小的价值还大且以及选满了,那我们就反悔选之前的物品,这样一定是更优的。因此只需要维护一个小根堆。
代码
#include<bits/stdc++.h>
#define pii pair<int,int>
#define eps 1e-7
#define equals(a,b) (fabs(a - b) < eps)
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
const ll MOD = 1e9 + 7;
ll rd(){
ll x = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int main(){
int n = rd();
ll ans = 0;
priority_queue<int,vector<int>,greater<int>> q;
vector<pii> v(n);
for(int i = 0;i < n;i++){
v[i].fi = rd();
v[i].se = rd();
}
sort(v.begin(),v.end());
for(int i = 0;i < n;i++){
if(v[i].fi <= q.size()) {
if(v[i].se > q.top()) {
ans -= q.top();
q.pop();
q.push(v[i].se);
ans += v[i].se;
}
}
else {
q.push(v[i].se);
ans += v[i].se;
}
}
cout << ans;
}