[Usaco2004 Feb]Moo University -- Financial Aid 财政补助

Moo University – Financial Aid 财政补助

— 题目来源:[Usaco2004 Feb]

描述:

  贝茜统计到人类拥有很多大学可以去就读,而奶牛们却一个大学也没有.
  为了解决这个问题,她和她的同伴们建立了一所奶牛大学Moo大学.
  为了防止笨牛入学,学校的创立者搞了一个奶牛智力测试(CSAT),它的分数在区间[1,2×10^9]内.
  Moo大学的学费很昂贵:不是所有奶牛都能负担.
  事实上,大多数奶牛需要一些财政帮助a(0≤o≤100000).政府不会给奶牛任何资金,所以所有的资金都来自于学校有限的资金,资金总数为F(0≤F≤2×10^9).更糟的是,虽然有C(N≤C≤100000)头奶牛报考,Moo大学却只能接受N(1≤N≤19999)头奶牛,N为奇数.
  贝茜既要让这N头奶牛享受最大限度的教育资源,又要它们CSAT分数的中位数尽可能高.    这里说一下对于一个奇数个数组成的集合中中位数的概念.例如,集合3,8,9,7,5的中位数是7,因为有两个数小于7,有两个数大于7.   
  给出每头奶牛的分数和所需的财政补贴数,可以接纳的奶牛数,补助的资金总数,求出中位数最大的可能值.

(1)我们可以分别假设每一个数是中位数,即将成绩从大到小排序,从前往后遍历。
(2)因此,左右各选牛的个数为 ( m i d + 1 ) / 2 (mid+1)/2 (mid+1)/2,并使其和最小
(3)降低复杂度,选择队列维护左,右,选 ( m i d + 1 / 2 ) (mid+1/2) (mid+1/2)头牛花费最小值

复杂度 O ( n log ⁡ 2 n ) O(n\log_{2}{n}) O(nlog2n)
以下是代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
/* 
inline char gc(){
    static char now[1<<16],*T,*S;
    if(T==S){T=(S=now)+fread(now,1,1<<16,stdin);if(T==S)return EOF;}
    return*S++;
}
inline int read(){
    register char ch=gc();
    while((ch<'0'||ch>'9')&&ch!='-')ch=gc();
    register bool neg=ch=='-';
	register int in=neg?0:ch-'0';ch=gc();
    while(ch>='0'&&ch<='9')in=(in<<3)+(in<<1)+ch-'0',ch=gc();
    return neg?-in:in;
}
*/
inline int read(){
    register char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    register bool neg=ch=='-';
	register int in=neg?0:ch-'0';ch=getchar();
    while(ch>='0'&&ch<='9')in=(in<<3)+(in<<1)+ch-'0',ch=getchar();
    return neg?-in:in;
}
struct Cow_Info{int score,money;};
priority_queue<Cow_Info>q1,q2;
inline bool operator<(const Cow_Info&l,const Cow_Info&r){return l.money<r.money;}
inline bool cmp(const Cow_Info&l,const Cow_Info&r){ return l.score>r.score; }
static Cow_Info a[100005];
static int n,c,f,b[100005],d[100005];
int main(){
    freopen("finance.in","r",stdin);
    freopen("finance.out","w",stdout);
    n=read(),c=read(),f=read(); 
    for(register int i=1;i<=c;i++)a[i].score=read(),a[i].money=read();
    sort(a+1,a+c+1,cmp);
    for(register int i=1,j=c;i<=n/2;i++,j--){
	    q1.push((Cow_Info){a[i].score,a[i].money});
        b[i]=b[i-1]+a[i].money;
        q2.push((Cow_Info){a[j].score,a[j].money});
        d[j]=d[j+1]+a[j].money; 
    }
    for(register int i=n/2+1,j=c-n/2;i<=c-n/2;i++,j--){
	    b[i]=b[i-1];
        if(a[i].money<q1.top().money){
		    b[i]=b[i]-q1.top().money+a[i].money;
            q1.pop();
            q1.push((Cow_Info){a[i].score,a[i].money});
        }
        d[j]=d[j+1];
        if(a[j].money<q2.top().money){
		    d[j]=d[j]-q2.top().money+a[j].money;
            q2.pop();
            q2.push((Cow_Info){a[j].score,a[j].money}); 
        } 
    }
    for(register int i=n/2+1;i<=c-n/2;i++)
    if(a[i].money+b[i-1]+d[i+1]<=f){
	    printf("%d",a[i].score);
        return 0;
    }
    printf("-1\n");
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值