題意: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;
}