Luogu 2949(倒序贪心)

传送门

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章