堆 poj 2010
选n个人从c个中 花费不超过f
c个人的成绩和花费
求分数中位数最大 n是奇数
显然中位数是n/2+1 ~c-n/2之间的(假如存在的话)
用大顶堆维护前n/2个小的花费 求出以这个人为中位数的花费
同理求出后面n/2个人的最小花费
然后判断一下即可
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> using namespace std; #define MAXN 100010 struct cow { int l,r,sc,co; }x[MAXN]; struct node//大顶堆 { int Size; int z[MAXN]; void clear() { Size=0; memset(z,0,sizeof(z)); } bool empty() { return Size?0:1; } void shift_up(int a) { while(a>1) { if(z[a]>z[a>>1]) { swap(z[a],z[a>>1]); a=a>>1; } else break; } } void shift_down(int a) { while((a<<1)<=Size) { int b=a<<1; if(b<Size&&z[b]<z[b+1]) b++; if(z[a]<z[b]) { swap(z[a],z[b]); a=b; } else break; } } int top() { return z[1]; } void pop() { swap(z[1],z[Size]); Size--; shift_down(1); } void push(int a) { z[++Size]=a; shift_up(Size); } }; bool cmp(cow a,cow b) { return a.sc<b.sc; } int main() { int n,c,f; scanf("%d%d%d",&n,&c,&f); for(int i=1;i<=c;i++) scanf("%d%d",&x[i].sc,&x[i].co); sort(x+1,x+c+1,cmp); node Q; Q.clear(); int sum=0; for(int i=1;i<=n/2;i++) { Q.push(x[i].co); sum+=x[i].co; } for(int i=n/2+1;i<=c-n/2;i++) { x[i].l=sum; int q=Q.top(); int p=x[i].co; if(p<q) { Q.pop(); sum=sum+p-q; Q.push(p); } } Q.clear(); sum=0; for(int i=c;i>c-n/2;i--) { Q.push(x[i].co); sum+=x[i].co; } for(int i=c-n/2;i>=n/2+1;i--) { x[i].r=sum; int q=Q.top(); int p=x[i].co; if(p<q) { Q.pop(); sum=sum+p-q; Q.push(p); } } int i; for(i=c-n/2;i>=n/2+1;i--) if(x[i].co+x[i].l+x[i].r<=f) break; if(i>=n/2+1) printf("%d\n",x[i].sc); else printf("-1\n"); return 0; }
posted on 2016-12-09 13:12 HelloWorld!--By-MJY 阅读(186) 评论(0) 编辑 收藏 举报