POJ 2010 - Moo University - Financial Aid
引用来自http://www.cnblogs.com/iiyiyi/p/4738644.html的思路:
【题目大意】
给出C头奶牛的SAT成绩和申请奖学金,选出N头牛,使得总奖学金在≤F的情况下奶牛SAT成绩的中位数最大。
【思路】
假设before[i]表示前i头奶牛中n/2头奶牛奖学金总额的最小值,而after[i]表示后i头奶牛中n/2头奶牛奖学金总额的最小值。
将C头奶牛按照SAT成绩进行排序后,从第c-n/2头开始到第n/2+1头奶牛进行枚举,如果当前before[i]+after[i]+当前奶牛申请的奖学金≤F,则退出,当前奶牛SAT成绩就是中位数的最大值。那么如何求before和after呢?可以用优先队列进行预处理。
以before为例,每新加入一头奶牛,就把它申请的奖学金累加到sum中去。如果当前优先队列的size大于n/2,则让队首(即申请奖学金最多的那一个)出队。这样,sum的总和始终未前i头奶牛中,n/2头奶牛奖学金总和的最小值。after同理从后往前做即可。
【错误点】
不要忘记了有可能是无解的,要输出-1;其次由于数组下标是0开始的,注意循环是[c-1-n/2,n/2]。
看discuss区有人说有多组数据,不写while会出错。(然而事实上并不是 摊手)
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 using namespace std; 5 struct Cows{ 6 int CSAT,aid; 7 }cow[100005]; 8 bool cmp(Cows a,Cows b) {return a.CSAT<b.CSAT;} 9 int main() 10 { 11 int n,c,f,before[100005],after[100005]; 12 scanf("%d%d%d",&n,&c,&f); 13 for(int i=1;i<=c;i++) scanf("%d%d",&cow[i].CSAT,&cow[i].aid); 14 sort(cow+1,cow+c+1,cmp); 15 int num=n/2,sum=0;//收n头牛,去掉中位数之后,剩下的左边有num头,右边也有num头 16 priority_queue<int> q1; 17 for(int i=1;i<=c;i++)//寻找在cow[i]之前的最小aid和,存入before[i] 18 { 19 sum+=cow[i].aid; 20 q1.push(cow[i].aid); 21 if(q1.size() > num) 22 { 23 sum-=q1.top(); 24 q1.pop(); 25 } 26 if(q1.size() == num) before[i]=sum; 27 } 28 priority_queue<int> q2; 29 sum=0; 30 for(int i=c;i>=1;i--)//寻找在cow[i]之后的最小aid和,存入after[i] 31 { 32 sum+=cow[i].aid; 33 q2.push(cow[i].aid); 34 if(q2.size() > num) 35 { 36 sum-=q2.top(); 37 q2.pop(); 38 } 39 if(q2.size() == num) after[i]=sum; 40 } 41 for(int i=c-num;i>num;i--) 42 { 43 if(before[i-1] + cow[i].aid + after[i+1] <= f){ 44 printf("%d\n",cow[i].CSAT); 45 return 0; 46 } 47 } 48 printf("-1\n"); 49 return 0; 50 }
转载请注明出处:https://dilthey.cnblogs.com/