POJ 2010 Moo University - Financial Aid 优先队列

题意:给你c头牛,并给出每头牛的分数和花费,要求你找出其中n(n为奇数)头牛,并使这n头牛的分数的中位数尽可能大,同时这n头牛的总花费不能超过f,否则输出-1.

思路:首先对n头牛按分数进行排序,然后假设当前这头牛X的分数为中位数,然后求出X前面n/2头牛的最小花费和,以及后面n/2头牛的最小花费和。

   因为按分数排序,X的前n/2和后n/2的牛的分数肯定分别大于等于X和小于等于X,所以X的分数肯定会是中位数。

   所以,我们令left[i]为牛i的前n/2头牛的最小花费和,right[i]为牛i的后n/2头牛的最小花费和,然后i从c-1到0遍历,求出第一个头牛的left[i]+right[i]+X的花费 ≤ f,该头牛的分数就是所求出的最大中位数。

AC代码:

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int MAX_N = 100005;
int n,c,f, left[MAX_N], right[MAX_N], half,total,result;
pair<int, int> w[MAX_N];
void solve()
{
half = n/2;
total = 0; priority_queue<int> q;
for(int i = 0; i < c; i++)
{
left[i] = q.size() == half ? total : 0x3f3f3f3f;
q.push(w[i].second);
total += w[i].second; if(q.size() > half)
{
total -= q.top();
q.pop();
}
} total = 0;
while(!q.empty()) q.pop();
for(int i = c-1; i >= 0; i--)
{
right[i] = q.size() == half ? total : 0x3f3f3f3f;
q.push(w[i].second);
total += w[i].second;
if(q.size() > half)
{
total -= q.top();
q.pop();
}
} result = -1;
for(int i = c-1; i >= 0; i--)
{
int x = left[i] + w[i].second + right[i];
if(x <= f)
{
result = w[i].first;
break;
}
}
printf("%d\n", result);
}
int main()
{
scanf("%d %d %d", &n, &c, &f);
for(int i = 0; i < c; i++)
scanf("%d %d", &w[i].first, &w[i].second);
sort(w,w+c);
solve();
return 0;
}

  

上一篇:nginx 1.安装


下一篇:SpringTest 使用说明 -构建无污染纯绿色事务测试框架 (记录用)