淘汰分数
淘汰分数
http://www.nowcoder.com/questionTerminal/9c4a4e879b4f49939dfaebea8948f976
/*
@Yuanjrah@
感谢 @地大小菜 的建议,对原始回答进行了修改
n个选手成绩,要想晋级和淘汰的人数均在[x,y]之间,
对成绩排序,然后输出最低位合适的位置即可,对于合适位置的判断分以下几种情况
1.x>n/2, 如n=100,[59,60]
晋级和淘汰都大于58,总人数超过100,不成立,输出-1
2.y<n/2+n%2, 如n=100,[2,4]
晋级和淘汰人数都小于5,总人数小于10,则小于100,不成立,输出-1
特殊情况,如n=101,[49,50]
晋级人数和淘汰人数都小于等于50,总人数小于等于100<n=101,不成立,输出-1,
如果y1=y+1=50+1,则,ans=49,成立
3.符合条件的最低的分数线
3.1以x为基准
如n=100,[49,55]
如果选择第x=49个,那么前49,后51,成立,由于是升序(已排序),
所以第49个必定最小
3.2以y为基准
如n=100,[5,55]
如果选择第x=5个,那么前5,后95,95>y=55,不成立
分析:选择一个位置m,使得分数低的人数nums_low和分数高的人数nums_high,
都在[x,y]区间,
必有 x<m<y && x<n-m<y ,n-m代表晋级人数
又因为选择最小分数,所以,位置max(x,n-y)为答案
即 m=y; while(m>=x) if(suit(m)) m--;
//suit(m)代表m的位置满足
x<m<y && x<n-m<y
4.特例 存在分数相等的情况
例如
6 2 3
1 2 2 2 3 3
选择2就会分成【4,2】,与题意不符
对于
6 2 3
1 2 2 3 3 3
选择2就可以
对于这种情况需要从非特例方案选择出位置pos, 然后往后搜寻,
找出第一个与pos位置值不一样的位置,
得到前后两端元素个数,判断是否满足题目要求即可
*/
scanf("%d %d %d", &n, &x, &y); int num, ans=0; int nums[50005]; for(int i=0; i<n; i++){ scanf("%d", &num); nums[i]=num; } sort(nums, nums+n); if(x>n/2|| y<n/2+n%2){ ans=-1; }else{ int less=n-y; less=less>x?less:x; ans=nums[less-1];//从0开始 int i; for(i=less; i<n; i++){ if(nums[i]!=ans){ break; } } if(n-i>=x&& n-i<=y&&i>=x&& i<=y){ }else{ ans=-1; } } cout<<ans; return 0; }