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;
}

 

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