POJ---2010(Moo University - Financial Aid,优先队列)

题意:

一共C个学生,学校要录N(奇数)个,每个学生的分数和需要的aid给出,学校最多能提供F资金,求录取的学生中分数中位数最大。

题解:

方法1:对所有的学生按照分数进行从小到大排序,左边从第N/2+1个学生开始,到第C-N/2个学生结束,算出每个学生以他的分数为中位数,左边需要的最小总aid,需要用到优先队列!

同样地,对右边也进行计算,以每个学生自身为中位数,右边需要的最小总aid

最后从右往左扫描,算出以每个学生为中位数,左右需要的总aid<=F即可!

 

 

方法2:二分。对于每个mid看是否满足左右两边的score=N/2,并且aid<=F


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>


using namespace std;

    struct node
    {
        int score,aid,left,right;
    };
bool cmp(struct node x1,struct node x2)
{
    return x1.score<x2.score;
}
struct node a[100000+5];

int main()
{   memset(a,0,sizeof(a));
    int N,C,F;
    cin>>N>>C>>F;
    for(int i=1; i<=C; i++)
        scanf("%d%d",&a[i].score,&a[i].aid);
    sort(a+1,a+C+1,cmp);

    priority_queue<int>q;
    int sum=0;

    if(N>1)
    {   //前N/2个肯定不能当中位数
        for(int i=1; i<=N/2; i++)
        {
            q.push(a[i].aid);
            sum+=a[i].aid;
        }
        //从N/2+1开始,计算分数比他小的N/2个最少需要多少aid
        for(int i=N/2+1; i<=C-N/2; i++)
        {
            a[i].left=sum;
            if(a[i].aid<q.top())
            {
                sum=sum-q.top()+a[i].aid;
                q.pop();
                q.push(a[i].aid);
            }
        }

        while(q.size())q.pop();

        sum=0;
        //右边同理;
        for(int i=C; i>C-N/2; i--)
        {
            q.push(a[i].aid);
            sum+=a[i].aid;
        }

        for(int i=C-N/2; i>=N/2+1; i--)
        {
            a[i].right=sum;
            if(a[i].aid<q.top())
            {
                sum=sum-q.top()+a[i].aid;
                q.pop();
                q.push(a[i].aid);
            }
        }
    }
    int ans=-1;
    for(int i=C-N/2; i>N/2; i--)
    {
        int total=a[i].left+a[i].right+a[i].aid;
        if(total<=F)
        {
            ans=a[i].score;
            break;
        }

    }
    cout<<ans<<endl;


}

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
using namespace std;
const int maxn=100000+5;

struct node{int rank_by_score,score,aid;};

node cow_score[maxn],cow_aid[maxn];

bool less_by_score(struct node a,struct node b)
{
    return a.score<b.score;
}

bool less_by_aid(struct node a,struct node b)
{
    return a.aid<b.aid;
}



int main()
{
    int N,C,F;
    cin>>N>>C>>F;

    for(int i=1;i<=C;i++)
        scanf("%d%d",&cow_score[i].score,&cow_score[i].aid);
     sort(cow_score+1,cow_score+1+C,less_by_score);
     for(int i=1;i<=C;i++)
            cow_score[i].rank_by_score=i;

     memcpy(cow_aid,cow_score,sizeof(node)*(C+1));

     sort(cow_aid+1,cow_aid+C+1,less_by_aid);

     int lb=1,ub=C,ans=-1;

     while(ub-lb>1)
     {
         int mid=(lb+ub)>>1;
         int left=0,right=0,total_aid=cow_score[mid].aid;
         for(int i=1;i<=C;i++)//按照aid从小到大 扫描
         {   //每次去找mid 左右两边 aid总和最小的。如果能找到符合条件的,则left,right最后应该都为N/2;
             //如果扫描一遍 left,right 都小于N/2,那么就是没有符合题意的解了。
             if(cow_aid[i].rank_by_score<mid && total_aid+cow_aid[i].aid<=F && left< N/2 )
             {
                 total_aid+=cow_aid[i].aid;
                 left++;
             }
             else if(cow_aid[i].rank_by_score>mid && total_aid+cow_aid[i].aid<=F && right< N/2 )
             {
                 total_aid+=cow_aid[i].aid;
                 right++;
             }

         }

         if(left<N/2 && right< N/2)//从小的aid开始选,都选不够N个
         {
             ans=-1;
             break;
         }

         else if(left < N/2)//放大
            lb=mid;
         else if(right<N/2)//缩小
            ub=mid;
         else
        {
            ans=cow_score[mid].score;
            lb=mid;//求最大
        }




     }

    cout<<ans<<endl;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值