# [USACO09OPEN]Work Scheduling 经典反悔贪心 ##
[USACO09OPEN]Work Scheduling 经典反悔贪心
题意
约翰有太多的工作要做。为了让农场高效运转,他必须靠他的工作赚钱,每项工作花一个单位时间。
他的工作日从 \(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)\)在给定的工作利润和截止时间下,约翰能够获得的利润最大为多少.
分析
限定的选择获得最大价值,我们肯定贪心地选择最大的价值。
对时间排序后,若该物品的价值比当前选的最小的价值还大且以及选满了,那我们就反悔选之前的物品,这样一定是更优的。因此只需要维护一个小根堆。
代码
#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;
}