POJ 2010 Moo University - Financial Aid (优先队列)

题意:从C头奶牛中招收N(奇数)头。它们分别得分score_i,需要资助学费aid_i。希望新生所需资助不超过F,同时得分中位数最高。求此中位数。

思路:

先将奶牛排序,考虑每个奶牛作为中位数时,比它分数低(前面的)的那群牛的学费总和lower_i,后面的总和upper_i。然后从分数高往分数低扫描,满足aid_i + lower_i + upper_i <= F的第一个解就是最优解

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define MAX_COW 100000 + 16

int N, C, F;
pair<int, int> cow[MAX_COW];
// 牛i作为中位数时,lower[i]表示分数低于它的牛的学费总和,upper[i]表示分数高于它的牛的学费总和
int lower[MAX_COW], upper[MAX_COW];

int main()
{
	cin >> N >> C >> F;
	int half = N / 2;
	for (int i = 0; i < C; ++i)
	{
		cin >> cow[i].first >> cow[i].second;	// 分数  学费
	}
	sort(cow, cow + C);
	{
		int total = 0;
		priority_queue<int> q;
		for (int i = 0; i < C; ++i)
		{
			lower[i] = q.size() == half ? total : 0x3f3f3f3f;
			q.push(cow[i].second);
			total += cow[i].second;
			if (q.size() > half)
			{
				// 踢掉一个学费最高的
				total -= q.top(); q.pop();
			}
		}
	}

	{
		int total = 0;
		priority_queue<int> q;
		for (int i = C - 1; i >= 0; --i)
		{
			upper[i] = q.size() == half ? total : 0x3f3f3f3f;
			q.push(cow[i].second);
			total += cow[i].second;
			if (q.size() > half)
			{
				// 踢掉一个学费最高的
				total -= q.top(); q.pop();
			}
		}
	}

	int result;
	for (int i = C - 1; i >= 0; --i)
	{
		if (lower[i] + cow[i].second + upper[i] <= F)
		{
			result = cow[i].first;
			break;
		}
	}
	cout << result << endl;
	return 0;
}
posted @ 2017-08-16 21:42  demianzhang  阅读(284)  评论(0编辑  收藏  举报