POJ2010--Moo University-Financial Aid(优先队列)

题目大意:从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;
}


你可能感兴趣的:(POJ2010--Moo University-Financial Aid(优先队列))