题目描述
世博会志愿者的选拔工作正在 A 市如火如荼的进行。为了选拔最合适的人才,AA市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的150\%150%划定,即如果计划录取mm名志愿者,则面试分数线为排名第m \times 150\%m×150%(向下取整)名的选手的分数,而最终进入面试的选手为笔试成绩不低于面试分数线的所有选手。
现在就请你编写程序划定面试分数线,并输出所有进入面试的选手的报名号和笔试成绩。
输入格式
第一行,两个整数 n,m(5 ≤ n ≤ 5000,3 ≤ m ≤ n)n,m(5≤n≤5000,3≤m≤n),中间用一个空格隔开,其中nn表示报名参加笔试的选手总数,mm表示计划录取的志愿者人数。输入数据保证 m \times 150\%m×150%向下取整后小于等于 nn。
第二行到第 n+1n+1 行,每行包括两个整数,中间用一个空格隔开,分别是选手的报名号 k(1000 ≤ k ≤ 9999)k(1000≤k≤9999)和该选手的笔试成绩s(1 ≤ s ≤ 100)s(1≤s≤100)。数据保证选手的报名号各不相同。
输出格式
第一行,有22个整数,用一个空格隔开,第一个整数表示面试分数线;第二个整数为进入面试的选手的实际人数。
从第二行开始,每行包含22个整数,中间用一个空格隔开,分别表示进入面试的选手的报名号和笔试成绩,按照笔试成绩从高到低输出,如果成绩相同,则按报名号由小到大的顺序输出。
输入输出样例
输入 #1复制
6 3 1000 90 3239 88 2390 95 7231 84 1005 95 1001 88
输出 #1复制
88 5 1005 95 2390 95 1000 90 1001 88 3239 88
说明/提示
【样例说明】
m \times 150\% = 3 \times150\% = 4.5m×150%=3×150%=4.5,向下取整后为44。保证44个人进入面试的分数线为8888,但因为8888有重分,所以所有成绩大于等于8888 的选手都可以进入面试,故最终有55个人进入面试。
NOIP 2009 普及组 第二题
分析:
这道题把我写吐了,逻辑上并不复杂,然而还是不知道为什么只得了10分,现在想来应该适合我的手写快排有关。第一次写的使用的二维数组来存储编号和成绩,然后手写快排进行交换,但是到最后却WA很多,代码如下:
#include<iostream>
#include<math.h>
using namespace std;
int n,m;
int people[10000][3];
void quicksort(int left,int right);
void jg();
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>people[i][1]>>people[i][2];
quicksort(1,n);
/*
cout<<"test "<<endl;
for(int i=1;i<=n;i++)
cout<<people[i][1]<<" "<<people[i][2]<<endl;
*/
jg();
int k=floor(m*1.5);
int sum=k;
int lastcj=people[n-k+1][2];
for(int i=n-k;i>=1;i--)
{
if(lastcj==people[i][2])
sum++;
else
break;
}
cout<<lastcj<<" "<<sum<<endl;
for(int i=n;i>=n-sum+1;i--)
cout<<people[i][1]<<" "<<people[i][2]<<endl;
return 0;
}
void quicksort(int left,int right)
{
int low=left;
int high=right;
int temp=(low+high)/2;
do
{
while(people[low][2]<people[temp][2]) low++;
while(people[high][2]>people[temp][2]) high--;
if(low<=high)
{
int t1=people[low][1];
int t2=people[low][2];
people[low][1]=people[high][1];
people[low][2]=people[high][2];
people[high][1]=t1;
people[high][2]=t2;
low++;
high--;
}
}while(low<=high);
if(left<high) quicksort(left,high);
if(right>low) quicksort(low,right);
}
void jg()
{
int change=1;
while(change)
{
change=0;
for(int i=n;i>1;i--)
{
if(people[i][2]==people[i-1][2]&&people[i][1]>people[i-1][1])
{
int t1=people[i][1];
int t2=people[i][2];
people[i][1]=people[i-1][1];
people[i][2]=people[i-1][2];
people[i-1][1]=t1;
people[i-1][2]=t2;
change=1;
}
}
}
}
我先是想让这个手写快排变成从大往小(默认是从小往大),然后改了排序算法中的大于小于号,测试用例答案不变,但是跑起来只有10分,我百思不得其解,想着是不是最后那个卡人数的部分弄错了,然后改了很久,还是10分,我意识到问题或许不在那里,那就是成绩相同,学号小优先错了?也不对啊,我写了个jg函数专门就是为了解决这个问题的,输出也正常,那难道,是快排算法?
我有这个想法,因为我私自改了大于小于号,然后10分,我估计是我改的时候没注意到其他的,然后导致快排算法出了问题,但是样例是对的,这就很烦,我也没有什么好的数据去进行测试,那没办法了,不弄那么多花里花哨的了,改成从小到大排,然后一系列全是反序来的,然后20....
吐了,看看大家的吧,原来大家用了结构体和sort函数??????我不是没想过sort函数,但是每次涉及到多种情况的比较时,我就觉得sort函数没法用,它只能从小到大排序,今天算是开了眼界了.题解里的大神让我学会了一个新东西,sort排序
#include<algorithm>
sort(a+m,a+n/*,排序规则*/);
//a是数组名,m,n是排序的范围(从a[m]排到a[n])。 (m与排序规则可以省略,默认m=0,排序规则为从大到小)
可以自己写个cmp,来进行sort排序.......话不多说,改一下吧,不用二维数组了,用结构体吧,然后AC了,果然,问题还是出在手写快排算法上,也不知道究竟是哪里出了问题,毕竟上道题我手写快排也AC了,这道题就不行了,以后还是要研究下了,上AC代码:
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
struct People{
int num;
int score;
};
People people[10000];
int n,m;
bool cmp(People p1,People p2);
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>people[i].num>>people[i].score;
sort(people+1,people+1+n,cmp);
int k=floor(m*1.5);
int sum=k;
int lastcj=people[k].score;
for(int i=k+1;i<=n;i++)
{
if(lastcj==people[i].score)
sum++;
else
break;
}
cout<<lastcj<<" "<<sum<<endl;
for(int i=1;i<=sum;i++)
cout<<people[i].num <<" "<<people[i].score <<endl;
return 0;
}
bool cmp(People p1,People p2)
{
if(p1.score>p2.score)
return true;
if(p1.score<p2.score)
return false;
if(p1.score==p2.score)
{
if(p1.num<p2.num)
return true;
else
return false;
}
}