提意:
N个名额,C头牛申请入学,F是学校最多能提供的补助金总额。
每头牛有一个分数和需要的补助金。
要求N头入学的牛的分数的中间最大,并输出这个分数。如果不能让N头牛入学,则输出-1。
思路:
以每一头牛为中点,求出成绩比它高的N/2头牛的最小补助金和 和 比它低的N/2头牛的最小补助金和。
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
//思路:优先队列
int N,C,F;
pair<int,int> cow[100002];
priority_queue<int> que1,que2;
int low[100002],up[100002];
int total;
int main()
{
int i;
scanf("%d %d %d",&N,&C,&F);
for(i = 0; i < C; i++){
scanf("%d %d",&cow[i].first,&cow[i].second);
}
sort(cow,cow+C); //从小到大
int half=N/2; //中间值的位置
for(i = 0; i < C; i++){ //half前
low[i] = (que1.size() == half ? total : 10*0x7ffffff);
//以第i头牛分数为中值时,比它分数低的牛中所需助学金最低的half头牛的金额总数为low[i]
total += cow[i].second;
que1.push(cow[i].second);
while(que1.size() > half){
int temp = que1.top(); //最队列中把助学金最高的牛取出
total -= temp;
que1.pop();
}
}
total = 0;
for(i = C-1; i >= 0; i--){ //half后
up[i] = (que2.size() == half ? total : 10*0x7ffffff); //小心溢出
total += cow[i].second;
que2.push(cow[i].second);
if(que2.size() > half){
int temp = que2.top();
total -= temp;
que2.pop();
}
}
int ans=-1;
for(i = C-1; i >= 0; i--){ //从分数最高的牛开始,直到筛选出最高的中间值
if(low[i] + cow[i].second + up[i] <= F){
ans = cow[i].first;
break;
}
}
printf("%d\n",ans);
return 0;
}