题意:奶牛学校招生,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 }