题目大意:有c个牛,每个牛有分数c和学费f,现一共总可以提供F的学费给n个牛,问所有情况中c的中位数最大是多少;
题目解析:首先按照c排序,再枚举每头牛作为中位数进行判断,先预处理出L和R数组,代表第i头牛左边和右边n/2头牛f总和的最小值;一开始看着书上以为是二分,还能过,其实是不可以的,因为那个条件不满足二分的性质;
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n,c;
ll f,L[maxn],R[maxn];
struct node
{
ll c,f;
}q[maxn];
bool cmp(node a,node b)
{
if(a.c==b.c)
return a.f<b.f;
return a.c<b.c;
}
void init()
{
priority_queue<ll>p;
ll sum=0;
for(int i=0;i<c;i++)
{
if(i<n/2)
{
p.push(q[i].f);
sum+=q[i].f;
}
else
{
L[i]=sum;
sum+=q[i].f;
p.push(q[i].f);
sum-=p.top();
p.pop();
}
}
sum=0;
while(!p.empty()) p.pop();
for(int i=c-1;i>=0;i--)
{
if(i>c-1-n/2)
{
p.push(q[i].f);
sum+=q[i].f;
}
else
{
R[i]=sum;
sum+=q[i].f;
p.push(q[i].f);
sum-=p.top();
p.pop();
}
}
}
bool ok(int t)
{
return L[t]+R[t]+q[t].f<=f;
}
int main()
{
while(scanf("%d%d%lld",&n,&c,&f)!=EOF)
{
for(int i=0;i<c;i++)
scanf("%lld%lld",&q[i].c,&q[i].f);
sort(q,q+c,cmp);
init();
int ans=-1;
for(int i=c-1-n/2;i>=n/2;i--)
{
if(ok(i))
{
ans=i;
break;
}
}
if(ans!=-1)
printf("%lld\n",q[ans].c);
else
printf("-1\n");
}
return 0;
}