题意:奶牛学校招生,c头奶牛报名,要选n头(n为奇数),学校是义务制,所以每头奶牛的学费都由学校负责。每头奶牛都由自己的考试分数和它需要花的学费,学校总共有f的资金,问合法招生方案中中间分数(即排名第(n+1)/2)最高的是多少。

题解:先将所有的奶牛按照分数由高到低排序,假设k是招的奶牛中排名中间的那头,按照排序可知,[1,k-1]中的奶牛必定被招了(n-1)/2头,[k+1,c]中也必定被招了(n-1)/2头,而且无论招的是谁,分数是怎么样,最后影响结果的都只是k的分数。于是,可以预处理dpl[i]代表[1,i]头牛中选出(n-1)/2头牛的最小花费,dpr[i]代表[i,c]头牛中选出(n-1)/2头牛的花费,预处理方法可以用一个大顶堆,复杂度nlogn,最后枚举中间牛复杂度n。

View Code
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 const int N=101000;
 7 int dpl[N],dpr[N];
 8 priority_queue<int> Q;
 9 struct Data
10 {
11     int s,f;
12 }cow[N];
13 bool comp(Data a,Data b)
14 {
15     if(a.s!=b.s)
16         return a.s>b.s;
17     else
18         return a.f<b.f;
19 }
20 int main()
21 {
22     int n,c,f;
23     while(scanf("%d%d%d",&n,&c,&f)!=EOF)
24     {
25         int nu=(n-1)/2;
26         for(int i=1;i<=c;i++)
27             scanf("%d%d",&cow[i].s,&cow[i].f);
28         sort(cow+1,cow+c+1,comp);
29         while(!Q.empty())
30             Q.pop();
31         int sum=0;
32         for(int i=1;i<=nu;i++)
33             Q.push(cow[i].f),sum+=cow[i].f;
34         dpl[nu]=sum;
35         for(int i=nu+1;i<=c;i++)
36         {
37             if(cow[i].f>=Q.top())
38                 dpl[i]=sum;
39             else
40             {
41                 sum=sum-Q.top()+cow[i].f;
42                 Q.pop();
43                 Q.push(cow[i].f);
44                 dpl[i]=sum;
45             }
46         }
47         sum=0;
48         while(!Q.empty())
49             Q.pop();
50         for(int i=c;i>=c-nu+1;i--)
51             Q.push(cow[i].f),sum+=cow[i].f;
52         dpr[c-nu+1]=sum;
53         for(int i=c-nu;i>=1;i--)
54         {
55             if(cow[i].f>=Q.top())
56                 dpr[i]=sum;
57             else
58             {
59                 sum=sum-Q.top()+cow[i].f;
60                 Q.pop();
61                 Q.push(cow[i].f);
62                 dpr[i]=sum;
63             }
64         }
65         bool flag=false;
66         for(int i=nu+1;i<=c-nu;i++)
67         {
68             if(cow[i].f+dpl[i-1]+dpr[i+1]<=f)
69             {
70                 flag=true;
71                 printf("%d\n",cow[i].s);
72                 break;
73             }
74         }
75         if(!flag)
76             printf("-1\n");
77     }
78     return 0;
79 }