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