POJ2010--Moo University-Financial Aid(二分)

题目大意:在C头牛里选N头牛,在不超过经费F的情况下,使得N头牛的得分中位数最大。


分析:首先,既然有两个属性,我们可以分别开两个数组,一个数组按成绩升序,一个数组按经费升序。二分中位数那头牛mid,然后按经费从少到多,添加mid两边的牛。再进行判断,四种情况,见代码。


代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 222222;

struct Cow{
    int rank, score, aid;
};
Cow c_aid[maxn], c_score[maxn];
int N, C, F;

bool cmpa(Cow & i, Cow & j) {
    return i.aid < j.aid;
}

bool cmps(Cow & i, Cow & j) {
    return i.score < j.score;
}

int main() {
    while(~scanf("%d%d%d", &N, &C, &F)) {
        for(int i = 0; i < C; i++)
            scanf("%d%d", &c_score[i].score, &c_score[i].aid);
        sort(c_score, c_score+C, cmps);
        for(int i = 0; i < C; i++)
            c_score[i].rank = i;
        memcpy(c_aid, c_score, sizeof(Cow)*C);
        sort(c_aid, c_aid+C, cmpa);
        int L = 0, R = C, ans = -1;
        while(R-L > 1) {
            int mid = (L+R)>>1;
            int left = 0, right = 0, tot = c_score[mid].aid;
            for(int i = 0; i < C; i++) {
                if((c_aid[i].rank < mid) && (tot+c_aid[i].aid <= F) && (left < N/2)) {
                    tot += c_aid[i].aid;
                    left++;
                }
                else if((c_aid[i].rank > mid) && (tot+c_aid[i].aid <= F) && (right < N/2)) {
                    tot += c_aid[i].aid;
                    right++;
                }
            }
            if(left < N/2 && right < N/2) {
                ans = -1;
                break;
            }
            else if(left < N/2) L = mid;
            else if(right < N/2) R = mid;
            else ans = c_score[mid].score, L = mid;
        }
        printf("%d\n", ans);
    }
    return 0;
}



你可能感兴趣的:(POJ2010--Moo University-Financial Aid(二分))