您的位置:首页 > 大数据 > 人工智能

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

2015-05-07 19:40 363 查看
http://poj.org/problem?id=2010

"Moo U"大学有一种非常严格的入学考试(CSAT) ,每头小牛都会有一个得分。然而,"Moo U"大学学费非常昂贵,并非每一头小牛都能支付的起,很多小牛都需要经济援助,但是学校只有有限的资金F。

"Moo U"大学只会从C个学生里选N个学生出来,(N是奇数),但是希望N头小牛CSAT得分的中位数越高越好。输入N,C,F 接下来C行,每行包括一个得分和需要申请的经济援助,输出符合条件的最大中位数。

首先对score排序,然后用堆维护前k小的数的和,左右扫描预处理,枚举中位数的位置。

就是把每个数i的前n/2个数的最小和求出来用sum1[i]保存,i的后n/2个数的最小和求出来用sum2[i]保存。

枚举中位数的时候只需要逆序枚举 p[i]+sum1[i]+sum2[i]<=F 满足条件的 i,输出中位数即可。

#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100010;
int N,C,F;
struct node
{
int s,c;
bool operator < (const node &a) const  //定义堆的优先级 为大根堆
{
return c<a.c;
}
}p[maxn];

bool cmp(const node& x,const node& y)  //按score排序
{
return x.s<y.s;
}
priority_queue<node>q1,q2;
int f1[maxn],f2[maxn];
void solve()
{
sort(p,p+C,cmp);
int sum1=0,sum2=0;
int ans=-1;   //没有符合条件的输出-1
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
for(int i=0;i<C;i++)
{
if(i<N/2)  // i<N/2的时候  这个i不能选
{
q1.push(p[i]);
sum1+=p[i].c;
continue;
}
f1[i]=sum1;   //i之前的n/2的最小值
if(p[i].c>=q1.top().c) continue;
sum1-=q1.top().c;  //如果i比当前堆中最大元素小,需要更新
q1.pop();
sum1+=p[i].c;
q1.push(p[i]);
}
for(int i=C-1;i>=0;i--)
{
if(i>C-1-N/2)
{
q2.push(p[i]);
sum2+=p[i].c;
continue;
}
f2[i]=sum2;
if(p[i].c>=q2.top().c) continue;
sum2-=q2.top().c;
q2.pop();
sum2+=p[i].c;
q2.push(p[i]);
}
for(int i=C-1-N/2;i>=N/2;i--)
{
if(f1[i]+f2[i]+p[i].c<=F)
{
ans=p[i].s;break;
}
}
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d%d",&N,&C,&F))
{
for(int i=0;i<C;i++)
scanf("%d%d",&p[i].s,&p[i].c);
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: