题意:输入 n,c,f(要选n头牛,共有c头牛,只有 f 的资金),接下来c行每行有a,b表示第i头牛的成绩为a,需要花费b元。问你在少于f的前提下,选出n头奶牛并是排序后第(n-1)/2的奶牛成绩最好。
考虑这道题的数据范围是100000,所以正解一定是有一个log级别的,可以想到二分和堆,数据结构,据说二分是错的,但是本题可以水过,但是为了正义,还是考虑正解吧。
明确本题的两个限制条件:1.奶牛的成绩 2.奶牛的花费
但是对于选出来的n头奶牛,只有第(n-1)/2头奶牛是对答案有贡献的,其他的都只是来看戏
所以定义 dpl和dpr表示以当前奶牛为中间的牛的前后最小花费(有优先队列和dp预处理出),然后O(n)判断
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
#define maxn 101030
#define Clear(x) memset(x,0,sizeof(x))
using namespace std;
int n,c,f,dpl[maxn],dpr[maxn];
priority_queue<int>q;
struct DATA{
int s,f;
bool operator <(const DATA& b )const{
return s==b.s?f<b.f:s>b.s;
}
}cow[maxn];
int main(){
while(scanf("%d%d%d",&n,&c,&f)!=EOF){
while(!q.empty())q.pop();
Clear(dpl);Clear(dpr);
for(int i=1;i<=c;i++)scanf("%d%d",&cow[i].s,&cow[i].f);
sort(cow+1,cow+1+c);
//for(int i=1;i<=c;i++)printf("%d %d\n",cow[i].s,cow[i].f );
int k=(n-1)/2,sum=0;
for(int i=1;i<=k;i++)sum+=cow[i].f,q.push(cow[i].f);
dpl[k+1]=sum;q.push(cow[k+1].f);sum+=cow[k+1].f;
for(int i=k+2;i<=c-k;i++){
sum-=q.top();q.pop();
dpl[i]=sum;
sum+=cow[i].f;q.push(cow[i].f);
}
while(!q.empty())q.pop();
sum=0;
for(int i=c;i>=c-k+1;i--)sum+=cow[i].f,q.push(cow[i].f);
dpr[c-k]=sum;q.push(cow[c-k].f);sum+=cow[c-k].f;
for(int i=c-k-1;i>k;i--){
sum-=q.top();q.pop();
dpr[i]=sum;
sum+=cow[i].f;q.push(cow[i].f);
}
bool ok=false;int ans=0;
for(int i=k+1;i<=c-k;i++){
if(dpl[i]+dpr[i]+cow[i].f<=f){
ok=true;
ans=max(ans,cow[i].s);
break;
}
}
if(ok)
printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
/*
5 18
20 20
30 25
35 30
50 21
*/