题目描述
农夫约翰有很多工作要做!为了高效地经营农场,他必须从他所做的每一项工作中赚取利润,每项工作只需要一个时间单位。
他的工作日从时间 0 开始,总共有 109 个时间单位。他目前可以从 N (1≤N≤105) 项工作中选择要做的工作,这些工作被方便地编号为 1 到 N。
虽然理论上他有可能完成所有 N 项工作,但实际上这是极不可能的,因为他在任何一个时间单位内只能完成一项工作,而截止日期通常会导致他无法完成所有任务。
第 i 项工作的截止时间为 Di (1≤Di≤109)。如果他在截止时间前完成第 i 项工作(如果当前时间为 t,那么仅当 Di>t 的时候他能做这个任务,完成后 t→t+1),他将获得 Pi (1≤Pi≤109) 的利润。
给定一系列工作和截止日期,FJ 能够获得的最大总利润是多少?答案可能无法容纳在 32 位整数中。
输入格式
第一行输入一个整数 N,意义见题目描述。
第二行到第 N+1 行:第 i+1 行包含两个用空格分隔的整数:Di 和 Pi
输出格式
只有一个数字,表示 FJ 能够获得的最大利润。
显示翻译
题意翻译
输入输出样例
输入 #1复制
3 2 10 1 5 1 7
输出 #1复制
17
说明/提示
在时间 1 完成工作 3 (1,7),在时间 2 完成工作 1 (2,10) 以最大化收益,最后收益为 7+10=17。
(由 ChatGPT 4o 翻译)
思路:
当这个时间点有利润更高的工作时,将利润最少,也就是队首出队,将利润更高的入队。
代码:
#include<bits/stdc++.h>
using namespace std;
priority_queue<int, vector<int>, greater<int> > q;//小根堆
long long ans;
struct f{
long long a,b;
}f1[1000000];
bool g(f a, f b){
return a.a<b.a;//sort排序规则
}
int main(){
long long n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>f1[i].a>>f1[i].b;
}
sort(f1+1,f1+n+1,g);//排序
for(int i=1;i<=n;i++){
ans+=f1[i].b;
q.push(f1[i].b);//入队
if(q.size()>f1[i].a){
ans-=q.top();//反悔
q.pop();//出队
}
}
cout<<ans;
return 0;
}