poj2010

大学招n(n为奇数)个牛 招第i个牛需要ai块钱 第i个牛高考si分

输入招的牛数n 总的牛数c 总的钱数f

以及ai si

问用这些钱招的n个牛高考分数的中位数最大是多少

如果钱不够输出-1

这题结果只与中间那个牛的分数有关

设k=(n+1)/2

则可以得到分比k低的招了(n-1)/2个

比k高的也招了(n-1)/2个

用dpL[i]表示在[1,i]中招(n-1)/2个的最小花费

用dpR[i]表示在[i,c]中招(n-1)/2个的最小花费

排序 枚举k

如果满足dpL[i] + dpR[i] + ai <= F就可行

在可行情况下找最大的中位数就可以了

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=101000;
int dpl[N],dpr[N];
priority_queue<int> Q;
struct Data
{
    int s,f;
}cow[N];
bool comp(Data a,Data b)
{
    if(a.s!=b.s)
        return a.s>b.s;
    else
        return a.f<b.f;
}
int main()
{
    int n,c,f;
    while(scanf("%d%d%d",&n,&c,&f)!=EOF)
    {
        int nu=(n-1)/2;
        for(int i=1;i<=c;i++)
            scanf("%d%d",&cow[i].s,&cow[i].f);
        sort(cow+1,cow+c+1,comp);
        while(!Q.empty())
            Q.pop();
        int sum=0;
        for(int i=1;i<=nu;i++)
            Q.push(cow[i].f),sum+=cow[i].f;
        dpl[nu]=sum;
        for(int i=nu+1;i<=c;i++)
        {
            if(cow[i].f>=Q.top())
                dpl[i]=sum;
            else
            {
                sum=sum-Q.top()+cow[i].f;
                Q.pop();
                Q.push(cow[i].f);
                dpl[i]=sum;
            }
        }
        sum=0;
        while(!Q.empty())
            Q.pop();
        for(int i=c;i>=c-nu+1;i--)
            Q.push(cow[i].f),sum+=cow[i].f;
        dpr[c-nu+1]=sum;
        for(int i=c-nu;i>=1;i--)
        {
            if(cow[i].f>=Q.top())
                dpr[i]=sum;
            else
            {
                sum=sum-Q.top()+cow[i].f;
                Q.pop();
                Q.push(cow[i].f);
                dpr[i]=sum;
            }
        }
        bool flag=false;
        for(int i=nu+1;i<=c-nu;i++)
        {
            if(cow[i].f+dpl[i-1]+dpr[i+1]<=f)
            {
                flag=true;
                printf("%d\n",cow[i].s);
                break;
            }
        }
        if(!flag)
            printf("-1\n");
    }
    return 0;
}

时间: 2024-10-14 19:25:22

poj2010的相关文章

poj2010 Moo University - Financial Aid

Moo University - Financial Aid 题意: 一个私立学校的学生要申请奖学金,而学校的金额有限.因此,学校希望在金额不超过F的情况下从C中选得N对数. 给出三个数N,C,F.分别代表在C对数中要取得N对数. 而每对数分别代表成绩,跟申请金额.要求取得N对数中的总金额不超过F的条件下,然取得中间的以为学生的成绩最高.(N为even) 算法分析: 本题有两种解法,一种是用优先队列,一种是二分; 一.利用堆实现 先说堆的实现方法,我们能够现对头尾的N/2进行处理,由于头尾的N/

POJ2010 Moo University - Financial Aid(二分法)

题目地址 分析:如果用二分法,关键是score和aid分开排序,score排序是为了充分利用中位数的性质,这样就可以确定m左右必须各选N/2个,到这之后有人是用dp求最优解,可以再次按照aid排序一次,可以直接确定最优解(肯定是从最小的开始选择!): 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 int N, C, F; 6 const i

poj2010(Moo University - Financial Aid)优先队列

Description Bessie noted that although humans have many universities they can attend, cows have none. To remedy this problem, she and her fellow cows formed a new university called The University of Wisconsin-Farmside,"Moo U" for short. Not wish

POJ_2010 Moo University - Financial Aid 【堆预处理】

一.题面 POJ2010 二.分析 堆预处理 首先可以考虑吧随便取一个点,判断两侧的最小的总费用是多少,然后相加判断是否满足条件.如果直接判断会超时,所以需要用大根堆预处理一下.先看从分数最小的往最大的预处理,先取N/2个相加,并把他们都加入到堆中,先假设这个和值是最大的,然后不断往后扫描的过程中,不断更新大根堆的根值,以及它的和.反向预处理类似.比较容易出错的是选的范围,如果不用那些不可能到的点,可以随意点,但如果需要使用这些点,需要用足够大的值填充. 三.AC代码 1 #include <c

挑战程序设计竞赛3.1习题:Moo University - Financial Aid POJ - 2010

(原题见POJ2010) 这道题我之前采用了优先队列+预处理的方法求解(https://www.cnblogs.com/jacobfun/p/12244509.html),现在用二分的办法进行求解. 一开始我很纳闷,采用二分求解本题,如果二分的mid值不符合条件,按照二分右边界应该为mid - 1(我采用前闭后闭的二分),那么如果mid + xxx(xxx大于0)可以呢?(考虑mid不行是因为左边最小加起来大了,mid ~ mid + xxx中有极小值,使得mid + xxx的左边可以满足,那么