题意:n个工作,每个工作有DDL和收益,每个时间点最多跟一项工作(该工作只消耗该时间点),求选择某些工作能获得的最大收益
题解:
1. “后悔法”:(留坑待填)
2. 蜜汁倒序贪心:
按时间倒着排序,DDL大的放前面,然后每一轮把DDL的相同的扔进优先队列里(权值大的在队首),之后从后往前枚举时间点进行贪心。
考虑到每从优先队列取出一个元素就需要将DDL相同的元素的DDL减一(同一个时间点只能干一项工作),这个可能可以用数据结构操作...吧◔ ‸◔?。但是可以想一个偷懒的方法--记录当前考虑到的时间cur,没取出一个元素就cur--,减到跟下一轮DDL为止(因为再取出的话就要考虑下一轮DDL的元素)。
大概就是这样......
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1e6+4;
int n;
ll sum;
struct Node {
int v,t;
friend bool operator <(const Node x,const Node y) {
return x.v<y.v;
}
}a[N];
priority_queue<Node> q;
bool cmp(const Node x,const Node y) {
return x.t>y.t||(x.t==y.t&&x.v>y.v);
}
inline int read() {
int x=0;char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
int main() {
// freopen("in.txt","r",stdin);
n=read();
for (register int i=1;i<=n;++i)
a[i].t=read(),a[i].v=read();
sort(a+1,a+n+1,cmp);
int cur=a[1].t,i=1;
while (1) {
while (a[i].t==cur)
q.push(a[i]),++i;
while (!q.empty()&&a[i].t<cur) {
sum+=q.top().v;
q.pop();
--cur;
}
if (i>n) break;
cur=min(a[i].t,cur);
}
printf("%lld\n",sum);
return 0;
}