嘘~ 正在从服务器偷取页面 . . .

洛谷P2949 [USACO09OPEN]Work Scheduling G 题解


洛谷P2949 [USACO09OPEN]Work Scheduling G 题解

题目链接:P2949 [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 )\)

在给定的工作利润和截止时间下,约翰能够获得的利润最大为多少。

反悔型贪心经典题。

先把所有的工作按时间限制顺序排序。

然后我们从前往后扫一遍,遇到能做的工作就把它吃了

如果没法做,我们就把之前吃过的价值比它小的给吐出来。

这个过程等价于当时就选了这个工作,只不过当时还没遇到,先吃个垃圾占位。

我们可以用一个小根堆维护之前哪些工作可能成为垃圾。

时间复杂度 \(\mathcal{O}(n \log n)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e5+15))

int n,ans,d[N],p[N],o[N];
priority_queue< int,vector<int>,greater<int> > q;
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n;
    for(int i=1; i<=n; i++){ cin >> d[i] >> p[i]; o[i]=i; }
    sort(o+1, o+1+n, [](int a,int b) { return d[a] < d[b]; });
    for(int i=1; i<=n; i++)
    {
        int &P = p[o[i]], &D = d[o[i]];
        if(D > q.size())
        {
            q.push(P);
            ans += P;
        }else
        {
            if(q.top() < P)
            {
                ans += P - q.top();
                q.pop(); q.push(P);
            }
        }
    }
    cout << ans << '\n';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录