【题意】
有c(c<=100000)头奶牛,现要招收n(n是奇数,n<=19999)头奶牛上大学,给定每头奶牛的智商和所需补助,并给定最大可提供补助和f(f<=2*10^9),
求补助奶牛的智商最大中位数
【输入】
第一行n、c、f
接下来c行每行两个数字,分别为智商和所需补助
【输出】
一个数字,表示补助奶牛的智商最大中位数
若不存在补助方案则输出-1
不错的题
很容易想到将奶牛按智商从小到大排序,然后枚举中位数
那么问题就是如何确定中位数左右分别选取n div 2头奶牛的最小费用
这个可以通过堆预处理得出
正向扫描一遍每次看当前奶牛所需费用是否小于堆顶元素费用,若小于队顶出堆,当前奶牛费用入堆
反向同理
然后枚举一下中位数即可
program poj2010; var n,c,f,i,j,k,ans,tot:longint; heap,cast,cost,suma,sumb:array [0..100001] of longint; procedure swap (var a,b:longint); var i:longint; begin i:=a; a:=b; b:=i; end; procedure qsort(s,e:longint); var i,j,k:longint; begin if s>=e then exit; i:=s; j:=e; k:=cast[(s+e) div 2]; while i<=j do begin while cast[i]<k do inc(i); while cast[j]>k do dec(j); if i>j then break; swap(cast[i],cast[j]); swap(cost[i],cost[j]); inc(i); dec(j); end; qsort(s,j); qsort(i,e); end; procedure insert (p:longint); var i:longint; begin inc(tot); heap[tot]:=p; heap[tot*2]:=-1; heap[tot*2+1]:=-1; i:=tot; while (i<>1)and(heap[i]>heap[i div 2]) do begin swap(heap[i],heap[i div 2]); i:=i div 2; end; end; procedure delete ; var i:longint; begin if tot=1 then begin dec(tot); exit; end; swap(heap[tot],heap[1]); heap[tot]:=-1; dec(tot); i:=1; while (heap[i]<heap[i*2])or(heap[i]<heap[i*2+1]) do if heap[i*2]>heap[i*2+1] then begin swap(heap[i],heap[i*2]); i:=i*2; end else begin swap(heap[i],heap[i*2+1]); i:=i*2+1; end; end; begin while not seekeof do begin read(n,c,f); for i:=1 to c do read(cast[i],cost[i]); qsort(1,c); ans:=-1; tot:=0; heap[1]:=-1; for i:=1 to n div 2 do begin suma[n div 2]:=suma[n div 2]+cost[i]; insert(cost[i]); end; for i:=n div 2 + 1 to c do if heap[1]>cost[i] then begin suma[i]:=suma[i-1]-heap[1]+cost[i]; delete; insert(cost[i]); end else suma[i]:=suma[i-1]; tot:=0; heap[1]:=-1; for i:=c downto c - n div 2 + 1 do begin sumb[c - n div 2 + 1]:=sumb[c - n div 2 + 1]+cost[i]; insert(cost[i]); end; for i:=c - n div 2 downto 1 do if heap[1]>cost[i] then begin sumb[i]:=sumb[i+1]-heap[1]+cost[i]; delete; insert(cost[i]); end else sumb[i]:=sumb[i+1]; for i:=c - n div 2 downto n div 2 + 1 do if cost[i]+suma[i-1]+sumb[i+1]<=f then begin ans:=cast[i]; break; end; writeln(ans); end; end.