首页 > 其他 > 详细

POJ 2010 Moo University - Financial Aid(优先队列,贪心,中位数)

时间:2021-04-18 11:23:05      阅读:15      评论:0      收藏:0      [点我收藏+]

题目链接

该题求的是中位数。故我们先将奶牛按分数进行升序排序。

由于一定是奇数。故该奶牛前面有n/2个,后面有n/2个。

故我们从n/2+1那个奶牛开始计算花费。不断把前面n/2个中花费最大的奶牛去除换成自己。(这就需要用到优先队列了)

之后再从后n/2+1个奶牛开始向前遍历。计算花费。

最后从后往前遍历。判断以该数为中位数,前n/2和后n/2和该数的花费是否小于上限。是的话直接返回答案即可。

AC代码如下:

#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<cstdio>
#include<set>
#include<vector>
#define MAXN 100005
#define MOD 1000000
#define ft first
#define sd second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii; 
int n,c,f;
pii a[MAXN];
ll lm[MAXN],rm[MAXN];//维护每个数对儿左边n/2个最小花费和,和右边n/2个最小花费和
priority_queue<ll> pq;//大顶堆
int main(){
    while(~scanf("%d%d%d",&n,&c,&f)){
        while(!pq.empty())
            pq.pop();
        for(int i=0;i<c;i++){
            scanf("%d%d",&a[i].ft,&a[i].sd);//f为分数,s为奖学金 
            lm[i]=0;rm[i]=0;
        }
        sort(a,a+c);//先按分数升序排序,分数相同按奖学金升序排序
        int tot=n/2;
        for(int i=0;i<=c-1-n/2;i++){//维护左边的
            if(i<n/2){//所有学员中前n/2个 
                pq.push(a[i].sd);
                lm[tot]+=a[i].sd;//第n/2+1个数左边的最小花费合 
            }else{
                ll no=lm[tot];
                if(a[i].sd>=pq.top())//如果没法更新花费。那么就让其和上面的相同 
                    lm[++tot]=no;
                else{//有更小的花费值
                    pq.push(a[i].sd);
                    lm[++tot]=no-pq.top()+a[i].sd;
                    pq.pop();
                }
            }
        }
        while(!pq.empty())
            pq.pop();
        tot=c-1-n/2;
        for(int i=c-1;i>=n/2;i--){//维护右边的
            if(i>c-1-n/2){//所有学员中后n/2个 
                pq.push(a[i].sd);
                rm[tot]+=a[i].sd;
            }else{
                ll no=rm[tot];
                if(a[i].sd>=pq.top())//如果没法更新花费。那么就让其和上面的相同 
                    rm[--tot]=no;
                else {//有更小的花费值
                    pq.push(a[i].sd);
                    rm[--tot]=no-pq.top()+a[i].sd;
                    pq.pop();
                }
            }
        }
        int id=-1;
        for(int i=c-1-n/2;i>=n/2;i--){//从后往前找最大合法中位数
            ll now=a[i].sd+lm[i]+rm[i];
            if(now<=f){
                id=a[i].ft;
                break;
            }
        }
        printf("%d\n",id);
    }
    return 0;
}

 

POJ 2010 Moo University - Financial Aid(优先队列,贪心,中位数)

原文:https://www.cnblogs.com/mikku39/p/14672426.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!