牛客練習賽40 B 小A與任務(貪心)

issue敲膩害發表於2020-12-27

傳送門

其實是個比較套路的貪心

按照結束時間排序,每個任務依次考慮過去

n o w now now代表當前做任務花費的時間

當我們要做第 i i i個任務的時候,首先讓 n o w + = x i now+=x_i now+=xi

這時候,如果 n o w now now不大於結束時間,就往後考慮

如果 n o w now now比結束時間大了,說明前面的任務需要用金幣來騰出時間

用哪些任務來騰時間最划算??當然是 z z z值比較小的那些任務

由於我們需要動態維護 [ 1 , i ] [1,i] [1,i]任務的 z z z

所以搞一個優先佇列即可,每次把當前任務壓入佇列

動態維護之前每個任務還有多少時間可以用金幣換,看程式碼就容易了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
struct node{
	int z,x,y;
	bool operator < (const node&tmp )	const{ return z<tmp.z; }
}a[maxn]; int n;
bool com( node a,node b ){ return a.y<b.y; }
priority_queue<node>q;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d%d%d",&a[i].z,&a[i].x,&a[i].y );
	sort( a+1,a+1+n,com );
	int now = 0;//目前花費的時間 
	double ans = 0;//做完[1,i]任務需要花費的最少金幣 
	for(int i=1;i<=n;i++)
	{
		q.push( a[i] );
		now += a[i].x;//加上完成時間 
		while( now>a[i].y )
		{
			node u = q.top(); q.pop();
			int k = min( now-a[i].y,u.x );//用金幣購買的時間 
			ans += 1.0*k/u.z;
			now -= k, u.x-=k;
			if( u.x )	q.push( u );
		}
	}
	printf("%.1f\n",ans); 
}

相關文章