POJ2010 Moo University - Financial Aid

题目链接:https://vjudge.net/problem/POJ-2010

题目大意:

  有 \(C\) 头牛,每头牛有一个分数和需要资助的钱。现在要资助 \(N\) 头牛,总资助金额不能超过 \(F\),又要使得这 \(N\) 头牛分数的中位数最大。问最大中位数是多少。

知识点:  优先队列

解题思路:

  先将 \(N\) 头牛根据分数从高到低排列,则其分数可能作为答案的牛所在区间为 \([N/2+1,C-N/2]\)。那么,我们就可以枚举该空间中的每一头牛,并且用 \(le(i)\) 和 \(ri(i)\) 记录下对于第 \(i\) 头牛在其前面和后面取 \(N\2\) 头牛所需要的最少资助金额,当在 \([N/2+1,C-N/2]\) 中枚举到一头牛 \(x\) 满足 \(le(x) + ri(x) + aid(x) \le F\),则停止枚举,输出答案。如果没有满足条件的牛,则输出 \(-1\).

  对于 \(le(x)\) 和 \(ri(x)\),我们维护一个优先队列来求解。

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <queue>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 typedef long long ll;
 8 const int maxn = 100005;
 9 struct cow{
10     ll score,aid;
11 }niu[maxn];
12 bool cmp(const cow &a,const cow &b){
13     return a.score>b.score;
14 }
15 priority_queue<ll> q;
16 ll le[maxn],ri[maxn];
17 int main(){
18     int N, C;
19     int j,i;
20     ll F;
21     while(scanf("%d%d%lld",&N,&C,&F)==3){
22         for(i=1;i<=C;i++)
23             scanf("%lld%lld",&niu[i].score,&niu[i].aid);
24         sort(niu+1,niu+1+C,cmp);
25         if(N==1){
26             bool can=false;
27             for(int i=1;i<=C;i++){
28                 if(niu[i].aid<=F){
29                     printf("%lld\n",niu[i].score);
30                     can=true;
31                 }
32             }
33             if(!can)    printf("-1\n");
34             continue;
35         }
36         ll sum=0;
37         for(i=1;i<=N/2;i++){
38             q.push(niu[i].aid);
39             sum+=niu[i].aid;
40         }
41         le[N/2+1]=sum;
42         for(i=N/2+1;i<C-N/2;i++){
43             if(niu[i].aid<q.top()){
44                 sum-=q.top();
45                 q.pop();
46                 q.push(niu[i].aid);
47                 sum+=niu[i].aid;
48             }
49             le[i+1]=sum;
50         }
51         while(!q.empty())   q.pop();
52         sum=0;
53         for(i=0,j=C;i<N/2;i++,j--)  q.push(niu[j].aid),sum+=niu[j].aid;
54         ri[j]=sum;
55         for(;j>N/2+1;j--){
56             if(niu[j].aid<q.top()){
57                 sum-=q.top();
58                 q.pop();
59                 q.push(niu[j].aid);
60                 sum+=niu[j].aid;
61             }
62             ri[j-1]=sum;
63         }
64         bool flag=false;
65         for(int i=N/2+1;i+N/2<=C;i++){
66             if(le[i]+ri[i]+niu[i].aid<=F){
67                 printf("%lld\n",niu[i].score);
68                 flag=true;
69                 break;
70             }
71         }
72         if(!flag)
73             printf("-1\n");
74     }
75 
76     return 0;
77 }

 

posted @ 2018-03-27 15:20  Blogggggg  阅读(145)  评论(0编辑  收藏  举报