题目大意:从C头牛里选N头牛,每头牛有两个属性,得分score和经费aid,在总经费不超过F的情况下使得N头牛的得分中位数最大。
分析:先将C头牛按得分score升序,然后,我们假设每个i都可以作为中位数,lower[i]记录在i之前(也就是分数比它低)的总经费,upper[i]记录在i之后(也就是分数比它高)的总经费,最后,由于是求最大的中位数,所以,得分从后往前循环,第一个满足lower[i]+aid[i]+upper[i]的i就是最优解。
在求lower[i]和upper[i]的时候用优先队列把最大值弹出。
代码:
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 111111;
pair<int, int> cow[maxn];
int lower[maxn], upper[maxn];
int main() {
int n, c, f;
while(~scanf("%d%d%d", &n, &c, &f)) {
memset(lower, -1, sizeof(lower));
memset(upper, -1, sizeof(upper));
for(int i = 0; i < c; i++)
scanf("%d%d", &cow[i].first, &cow[i].second);
sort(cow, cow+c);
int half = n/2;
int tot = 0;
priority_queue<int> pq;
for(int i = 0; i < c; i++) {
lower[i] = pq.size() == half ? tot : 1 << 30;
pq.push(cow[i].second);
tot += cow[i].second;
if(pq.size() > half) { //去掉经费最多的
tot -= pq.top();
pq.pop();
}
}
tot = 0;
while(!pq.empty()) {pq.pop();}
for(int i = c-1; i >= 0; i--) {
upper[i] = pq.size() == half ? tot : 1 << 30;
pq.push(cow[i].second);
tot += cow[i].second;
if(pq.size() > half) { //去掉经费最多的
tot -= pq.top();
pq.pop();
}
}
int ans = -1;
for(int i = c-1; i >= 0; i--) {
if(lower[i] + cow[i].second + upper[i] <= f) {
ans = cow[i].first;
break;
}
}
printf("%d\n", ans);
while(!pq.empty()) {pq.pop();}
}
return 0;
}