Moo University - Financial Aid POJ 2010(枚举)

原题

题目链接

题目分析

题目要求取中位数,我们可以枚举以每个牛的分数作为中位数,然后选出最省钱的方案,最后只需要看花钱数不超过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 }

 

posted @ 2019-08-27 14:09  VBL  阅读(91)  评论(0编辑  收藏  举报