洛谷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;
}
posted @ 2023-01-06 23:18  Zeoy_kkk  阅读(39)  评论(0编辑  收藏  举报