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; }