POJ 2010 Moo University - Financial Aid(优先队列or二分搜索—最大化K大值)

Moo University - Financial Aid
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 6572 Accepted: 1923

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 wishing to admit dumber-than-average cows, the founders created an incredibly precise admission exam called the Cow Scholastic Aptitude Test (CSAT) that yields scores in the range 1..2,000,000,000. 

Moo U is very expensive to attend; not all calves can afford it.In fact, most calves need some sort of financial aid (0 <= aid <=100,000). The government does not provide scholarships to calves,so all the money must come from the university's limited fund (whose total money is F, 0 <= F <= 2,000,000,000). 

Worse still, Moo U only has classrooms for an odd number N (1 <= N <= 19,999) of the C (N <= C <= 100,000) calves who have applied.Bessie wants to admit exactly N calves in order to maximize educational opportunity. She still wants the median CSAT score of the admitted calves to be as high as possible. 

Recall that the median of a set of integers whose size is odd is the middle value when they are sorted. For example, the median of the set {3, 8, 9, 7, 5} is 7, as there are exactly two values above 7 and exactly two values below it. 

Given the score and required financial aid for each calf that applies, the total number of calves to accept, and the total amount of money Bessie has for financial aid, determine the maximum median score Bessie can obtain by carefully admitting an optimal set of calves. 

Input

* Line 1: Three space-separated integers N, C, and F 

* Lines 2..C+1: Two space-separated integers per line. The first is the calf's CSAT score; the second integer is the required amount of financial aid the calf needs 

Output

* Line 1: A single integer, the maximum median score that Bessie can achieve. If there is insufficient money to admit N calves,output -1. 

Sample Input

3 5 70
30 25
50 21
20 20
5 18
35 30

Sample Output

35

Hint

Sample output:If Bessie accepts the calves with CSAT scores of 5, 35, and 50, the median is 35. The total financial aid required is 18 + 30 + 21 = 69 <= 70. 


题意:奶牛学校招生,要录取n(奇数)个学生,报名了c个学生,每个学生有成绩s_i和需要的补助金f_i。学校的补助金一共为F元,挑选n个学生,f_1+f_2+f_i+....+f_n不得大于n,且n个奶牛的s_i的中位数最大,输出这个数?


题解:

优先队列+枚举,分治解法:

将奶牛按照成绩s_i从小到大排序,从 n/2 到 m-1-n/2枚举中位数,记录每个i的前面n/2数的f之和,和后面n/2数的f之后,然后枚举满足条件最大的中位数。


代码如下:


#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
struct node
{
	int s,f;
	bool operator <(const node &x) const
	{
		return f<x.f;
	}
}cow[100010];

int minl[100000],minr[100000],n,m,F,suml,sumr;
//minl[i]表示i左边前n/2小的数的和,minr[i]表示i右边前n/2小的数的和 
int cmp(node a,node b)
{
	return a.s<b.s;
}

int main()
{
	int i,j;
	while(scanf("%d%d%d",&n,&m,&F)!=EOF)
	{
		for(i=0;i<m;++i)
			scanf("%d%d",&cow[i].s,&cow[i].f);
		sort(cow,cow+m,cmp);
		suml=0; sumr=0;
		priority_queue<node>ql,qr;//优先f大的元素先出队列 
		for(i=0;i<m;++i)//查找对于每个i左边n/2个元素的最小和 
		{
			if(i<n/2)
			{
				ql.push(cow[i]);
				suml+=cow[i].f;
				continue;
			}
			minl[i]=suml;
			if(cow[i].f<ql.top().f)
			{
				suml-=ql.top().f;
				ql.pop();
				suml+=cow[i].f;
				ql.push(cow[i]);
			}
		}
		for(i=m-1;i>=0;--i)//查找对于每个i右边n/2个元素的最小和
		{
			if(i>m-1-n/2)
			{
				qr.push(cow[i]);
				sumr+=cow[i].f;
				continue;
			}
			minr[i]=sumr;
			if(cow[i].f<qr.top().f)
			{
				sumr-=qr.top().f;
				qr.pop();
				sumr+=cow[i].f;
				qr.push(cow[i]);
			}
		}
		int ans=-1;
		for(i=m-1-n/2;i>=n/2;--i)//从大到小枚举满足条件的cow[i].s 
		{
			if(minl[i]+minr[i]+cow[i].f<=F)
			{
				ans=cow[i].s;
				break;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}



二分搜索—最大化最小值解法:


分别用分数和所需补助金给奶牛排序,用分数为界限将奶牛分为左右两区间两部分,再分别查找左区间满足条件的奶牛数 left  和右区间满足条件的奶牛数 right。  讨论 left 和 right 的值分情况取讨论如何修改下一次要查找的值。


具体内容见代码和注释:


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
	int s,f,id;
}cows[100010],cowf[100010];
int n,m,F;

int cmps(node a,node b)
{
	return a.s<b.s;
}

int cmpf(node a,node b)
{
	return a.f<b.f;
}

int dix(int x)
{
	int i,sum=cows[x].f,left=0,right=0;
	for(i=0;i<m;++i)
	{
		if(cowf[i].id<x&&(sum+cowf[i].f<=F)&&(left<n/2))
		{
			sum+=cowf[i].f;
			left++;
		}
		else if(cowf[i].id>x&&(sum+cowf[i].f<=F)&&(right<n/2))
		{
			sum+=cowf[i].f;
			right++;
		}
	}//以下是取当前mid值的方案可能出现四种情况 
	if((left<n/2)&&(right<n/2))//不可能满足条件,直接输出-1 
		return -1;
	else if(left<n/2)//不满足条件,但可能将mid值调大就满足条件了 
		return 1;
	else if(right<n/2)//不满足条件,但可能将mid值调小就满足条件了 
		return 2;
	return 0;//满足条件,但mid的值可能可以更大 
}

int main()
{
	int i,left,right,ans,mid;
	while(scanf("%d%d%d",&n,&m,&F)!=EOF)
	{
		for(i=0;i<m;++i)
			scanf("%d%d",&cows[i].s,&cows[i].f);
		sort(cows,cows+m,cmps);
		for(i=0;i<m;++i)
			cows[i].id=i;
		memcpy(cowf,cows,sizeof(cows));//内存拷贝函数,把cows[]拷贝给cowf[] 
		sort(cowf,cowf+m,cmpf);
		left=0; right=m; ans=-1;//注意ans初始化为-1可以省去后面的特判,没合适方案输出-1 
		while(left<=right)
		{
			mid=(left+right)>>1;
			switch(dix(mid))
			{
				case -1:{
					printf("-1\n");
					return 0;
				}
				case 0:{
					ans=cows[mid].s;
					left=++mid;
					break;
				}
				case 1:{
					left=++mid;
					break;
				}
				case 2:{
					right=--mid;
				}
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值