POJ-2010-优先队列

来源:互联网 发布:获取当前系统时间 java 编辑:程序博客网 时间:2024/06/07 00:36

题目大意:有c个牛,每个牛有分数c和学费f,现一共总可以提供F的学费给n个牛,问所有情况中c的中位数最大是多少;

题目解析:首先按照c排序,再枚举每头牛作为中位数进行判断,先预处理出L和R数组,代表第i头牛左边和右边n/2头牛f总和的最小值;一开始看着书上以为是二分,还能过,其实是不可以的,因为那个条件不满足二分的性质;

AC代码:

    #include<iostream>    #include<cstdio>    #include<cstring>    #include<string>    #include<algorithm>    #include<queue>    using namespace std;    typedef long long ll;    const int maxn=100010;    int n,c;    ll f,L[maxn],R[maxn];    struct node    {        ll c,f;    }q[maxn];    bool cmp(node a,node b)    {        if(a.c==b.c)        return a.f<b.f;        return a.c<b.c;    }    void init()    {        priority_queue<ll>p;        ll sum=0;        for(int i=0;i<c;i++)        {            if(i<n/2)            {                p.push(q[i].f);                sum+=q[i].f;            }            else            {                L[i]=sum;                sum+=q[i].f;                p.push(q[i].f);                sum-=p.top();                p.pop();            }        }        sum=0;        while(!p.empty())   p.pop();        for(int i=c-1;i>=0;i--)        {            if(i>c-1-n/2)            {                p.push(q[i].f);                sum+=q[i].f;            }            else            {                R[i]=sum;                sum+=q[i].f;                p.push(q[i].f);                sum-=p.top();                p.pop();            }        }    }    bool ok(int t)    {        return L[t]+R[t]+q[t].f<=f;    }    int main()    {        while(scanf("%d%d%lld",&n,&c,&f)!=EOF)        {            for(int i=0;i<c;i++)                scanf("%lld%lld",&q[i].c,&q[i].f);            sort(q,q+c,cmp);            init();            int ans=-1;            for(int i=c-1-n/2;i>=n/2;i--)            {                if(ok(i))                {                    ans=i;                    break;                }            }            if(ans!=-1)            printf("%lld\n",q[ans].c);            else            printf("-1\n");        }        return 0;    }



0 0