C. Playlist---(贪心+优先队列)Educational Codeforces Round 62 (Rated for Div. 2)

Playlist

题目链接http://codeforces.com/contest/1140/problem/C
time limit per test 2 seconds
memory limit per test 256 megabytes

在这里插入图片描述
在这里插入图片描述


题目大意:给你n个和k,接下来n行,每行a,b;让你选择最多k个数使其a的和乘以
min(b[i])的值最大。

这题先找到思路,我们现在前k个数中寻找最大值,之后我们每加入一个数就删掉一个数。先解决如何寻找最大值:我们将b从大到小排序,那么b[i]就是当前的b的最小值。然后我们直接做加法就好了,再进行比较要不要保留答案:ans=max(ans,sum*b[i])。接下来当个数大于k时,我们在插入一个数的同时减去一个数就好了,至于减去什么,我们可以减去a的最小值(或b的最小值)。所以我们可以大胆合理地猜测,然后WA几发A了它。。。(其实就算我们的b是最小的,我们删去了最小的b,由于之前我们是按照b排序的,也就是说删去它后的结果一定已经存在了,所以没必要考虑)
以下是详细代码:

#include <cstdio>
#include <algorithm>
#include <queue>
#define ll long long 
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
using namespace std;
const int mac=3e5+10;
struct node
{
	ll v,m;
	bool friend operator < (node a,node b){
		if (a.m==b.m) return a.v>b.v;
		return a.m>b.m;
	}
}a[mac];
priority_queue<ll,vector<ll>,greater<ll> >q; 
ll dp[mac];
int main()
{
	ll n,k;
	scanf ("%lld%lld",&n,&k);
	for (int i=1; i<=n; i++){
		scanf ("%lld%lld",&a[i].v,&a[i].m);
	}
	sort(a+1,a+1+n);
	ll maxx=0,sum=0;
	ll x=0;
	int i;
	for (i=1; i<=n; i++){
		sum+=a[i].v;
		q.push(a[i].v);
		if (q.size()>k){
			sum-=q.top();
			q.pop();		
		}
		x=max(sum*a[i].m,x);
	}
	printf ("%lld\n",x);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43906000/article/details/88919930