原题
题目分析
题目要求取中位数,我们可以枚举以每个牛的分数作为中位数,然后选出最省钱的方案,最后只需要看花钱数不超过F中的最高的中位数分数即可.说一下具体实现,先对所有牛按分数从小到大排序,选出最省钱的方案可以用优先队列来选,设half=n/2,当优先队列的牛超过half个的时候就把一个花费最多的弹出去,这样从小到大遍历一遍就可以记录分数比中位数小的那些牛的花费,记为lower[i],从大到小遍历一遍就可以记录分数比中位数大的那些牛的花费,记为upper[i],最后这个方案的总花费就是lower[i]+upper[i]+cow[i].cost.由于我们的牛是按分数从小到大排完序的,仔细观察可以发现最后这些方案具有二分性质,因此可以用二分快速找到答案.
代码
1 #include <iostream> 2 #include <algorithm> 3 #include <utility> 4 #include <cstdio> 5 #include <cmath> 6 #include <cstring> 7 #include <string> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <map> 12 #include <set> 13 14 using namespace std; 15 typedef long long LL; 16 const int INF_INT=0x3f3f3f3f; 17 const LL INF_LL=0x3f3f3f3f3f3f3f3f; 18 19 typedef pair<int,int> P; 20 int lower[200000],upper[200000]; 21 P cow[200000]; 22 23 void clear(priority_queue<int> &que) 24 { 25 priority_queue<int> empty; 26 swap(empty,que); 27 } 28 29 int main() 30 { 31 // freopen("black.in","r",stdin); 32 // freopen("black.out","w",stdout); 33 int n,c,f; 34 cin>>n>>c>>f; 35 for(int i=1;i<=c;i++) scanf("%d %d",&cow[i].first,&cow[i].second); 36 sort(cow+1,cow+1+c); 37 int half=n>>1; 38 int sum=0; 39 priority_queue<int> que; 40 for(int i=1;i<=c;i++) 41 { 42 if(i<=half) lower[i]=INF_INT; 43 else lower[i]=sum; 44 que.push(cow[i].second); 45 sum+=cow[i].second; 46 if(i>half) sum-=que.top(),que.pop(); 47 } 48 sum=0; 49 clear(que); 50 for(int i=c;i>=1;i--) 51 { 52 if(c-i<half) upper[i]=INF_INT; 53 else upper[i]=sum; 54 que.push(cow[i].second); 55 sum+=cow[i].second; 56 if(c-i>=half) sum-=que.top(),que.pop(); 57 } 58 // for(int i=1;i<=c;i++) printf("cow %d %d %d\n",i,cow[i].first,cow[i].second); 59 // for(int i=1;i<=c;i++) printf("up %lld low %lld\n",upper[i],lower[i]); 60 int l=half+1,r=c-half+1; 61 while(r-l!=1) 62 { 63 //printf("l=%d r=%d\n",l,r); 64 int mid=l+r; 65 mid>>=1; 66 if(upper[mid]+cow[mid].second+lower[mid]<=f) l=mid; 67 else r=mid; 68 } 69 if(upper[l]+cow[l].second+lower[l]>f) cout<<-1<<endl; 70 else cout<<cow[l].first<<endl; 71 72 /* int ans=-1; 73 for(int i=half+1;i<=c-half;i++) 74 if(upper[i]+lower[i]+cow[i].second<=f) ans=max(ans,cow[i].first); 75 cout<<ans<<endl;*/ 76 return 0; 77 }