题目:
http://poj.org/problem?id=2010
题意:
总费用为f,给你c头牛的分数和学费,从中选出n头牛,使其中位数最大且费用不超过总费用.
思路:
结构体记录分数和学费,按照分数从小到大排列.
使用优先队列预处理.先预处理出每个位置前面和后面的n/2头牛的最小花费,然后枚举每个位置,得到最后的答案.
AC.
#include <iostream>
#include <cstdio>
#include <queue>
#include <set>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 100005;
struct Num {
int score, aid;
bool operator < (const Num & X) const {
return score < X.score;
}
}num[maxn];
struct node {
int score, aid;
bool operator < (const node & X) const {
return aid < X.aid;
}
};
priority_queue<node> que;
int pay[maxn], pay2[maxn];
int n, c, f;
int main()
{
//freopen("in", "r", stdin);
while(~scanf("%d %d %d", &n, &c, &f)) {
int mid = n/2;
for(int i = 0; i < c; ++i) {
scanf("%d %d", &num[i].score, &num[i].aid);
}
sort(num, num + c);
int sum = 0;
node now, tmp;
while(que.size()) que.pop();
for(int i = 0; i < c-mid; ++i) {
now.score = num[i].score; now.aid = num[i].aid;
if(i >= mid) {
pay[i] = num[i].aid + sum;
sum += num[i].aid;
que.push(now);
tmp = que.top(); que.pop();
sum -= tmp.aid;
}
else {
que.push(now);
sum += num[i].aid;
}
}
sum = 0;
while(que.size()) que.pop();
for(int i = c-1; i >= mid; --i) {
now.score = num[i].score; now.aid = num[i].aid;
if(c - i > mid) {
pay2[i] = sum;
sum += num[i].aid;
que.push(now);
tmp = que.top(); que.pop();
sum -= tmp.aid;
}
else {
que.push(now);
sum += num[i].aid;
}
}
int ans = -1;
for(int i = mid; i + mid < c; ++i) {
if(pay[i] + pay2[i] <= f) ans = num[i].score;
}
printf("%d\n", ans);
}
return n;
}