finance 赞助学费
- Description
人类可以选择很多大学,而奶牛们却没学可上。为解决这个问题,贝西和她的伙伴们创立了一所奶牛大学,取名为哞哞大学。
为了选拔优秀学生,她们发明了一种奶牛学术能力测试(简称 CSAT),这种测试的分数异常精确,每头奶牛的成绩可以用0到2 × 10^9之间的一个整数表示,而且可以保证每头奶牛的分数都不同。
哞哞大学的学费很贵,奶牛们表示负担不起,他们都各自申请了奖学金。政府并没有为奶牛准备奖学金,所有的预算都必须要从学校有限的助学基金中扣除(设基金总额为F)。
哞哞大学有N间宿舍,N是一个奇数,所以贝西只能接受N头奶牛的申请,她发誓不会让入学的奶牛少于N。此外,她希望新生的 CSAT 成绩表现优异,她以中位数来衡量新生的总体水平。所谓中位数,就是排序后处在最中间的分数,比如3,8,9,7,5的中位数是7。
今年,共有C头奶牛申请入学,给定每头奶牛的 CSAT成绩和申请的奖学金数目,以及学校可赞助的总额,确定贝西接受哪些奶牛的申请才可以使成绩的中位数达到最大。
- Input Format
第一行:三个用空格分开的整数:N,C和F。1 ≤ N ≤ 19999,N ≤ C ≤ 10^5,0 ≤ F ≤ 2 × 10^9
第二行到C + 1行:每行有两个用空格分开的整数。第一个数是这头奶牛的 CSAT 成绩, 第二个数是这头奶牛需要的奖学金Qi,0 ≤ Qi ≤ 10^5。
- Output Format
第一行:一个整数,表示贝西可以得到的最大中位数,如果现有基金不够资助任何N头奶牛,则输出-1。
- Sample Input
3 5 70
30 25
50 21
20 20
5 18
35 30
- Sample Output
35
- Hint
样例解释:贝西接受 CSAT分数为5,35,50的奶牛的申请,中位数为 35,需支付的奖学金总额为18 + 30 + 21 = 69。
- 分析
由于一个物品有两个属性,所以我们考虑先按CSAT排序,如果以i为中位数,则i前后各有N/2个。然后我们用F[i]表示1~i取N/2个最小花费,G[i]表示i~C取N/2个最小花费。然后从后找一个Q[i]+F[i-1]+G[i+1]小于F的就可以了。
至于维护F和G,我们开个大根堆记录当前最小的N/2个,然后每次把Q[i]与堆顶比较取最小的即可。(详见代码)
#include <queue>
#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int N,C,f,F[100005],G[100005];
struct Data{int CSAT,Q;}A[100005];
inline bool cmp (const Data&A,const Data&B){return A.CSAT<B.CSAT;}
priority_queue <Data> Q1,Q2;
inline bool operator < (Data A,Data B){return A.Q<B.Q;}
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d%d%d",&N,&C,&f);
for (int i=1;i<=C;i++) scanf("%d%d",&A[i].CSAT,&A[i].Q);
sort(A+1,A+1+C,cmp);
for (int i=1,j=C;i<=N/2;i++,j--){
Q1.push(A[i]),F[N/2]+=A[i].Q,Q2.push(A[j]),G[C-N/2+1]+=A[j].Q;
}
for (int i=N/2+1,j=C-N/2;i<=C-N/2-1;i++,j--){
if (Q1.top().Q>A[i].Q) F[i]=F[i-1]-Q1.top().Q+A[i].Q,Q1.pop(),Q1.push(A[i]);
else F[i]=F[i-1];
if (Q2.top().Q>A[j].Q) G[j]=G[j+1]-Q2.top().Q+A[j].Q,Q2.pop(),Q2.push(A[j]);
else G[j]=G[j+1];
}
for (int i=C-N/2;i>=N/2+1;i--)
if (A[i].Q+F[i-1]+G[i+1]<=f){
printf("%d",A[i].CSAT);
fclose(stdin); fclose(stdout);
return 0;
}
printf("-1");
fclose(stdin); fclose(stdout);
return 0;
}