EXCEL排序
http://codeup.cn/contest.php?cid=100000581
-
题目描述
Excel可以对一组纪录按任意指定列排序。现请你编写程序实现类似功能。
对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3 时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。 -
输入
测试输入包含若干测试用例。每个测试用例的第1行包含两个整数 N (N<=100000) 和 C,
其中 N 是纪录的条数,C 是指定排序的列号。以下有N行,每行包含一条学生纪录。每条学
生纪录由学号(6位数字,同组测试中没有重复的学号)、姓名(不超过8位且不包含空格
的字符串)、成绩(闭区间[0, 100]内的整数)组成,每个项目间用1个空格隔开。当读到 N=0 时,全部输入结束,相应的结果不要输出。 -
输出
对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在
N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名
的非递减字典序排序;当 C=3 时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。 -
样例输入
4 1
000001 Zhao 75
000004 Qian 88
000003 Li 64
000002 Sun 90
4 2
000005 Zhao 95
000011 Zhao 75
000007 Qian 68
000006 Sun 85
4 3
000002 Qian 88
000015 Li 95
000012 Zhao 70
000009 Sun 95
0 3
- 样例输出
Case 1:
000001 Zhao 75
000002 Sun 90
000003 Li 64
000004 Qian 88
Case 2:
000007 Qian 68
000006 Sun 85
000005 Zhao 95
000011 Zhao 75
Case 3:
000012 Zhao 70
000002 Qian 88
000009 Sun 95
000015 Li 95
问题分析:
由题目可定义如下的结构体:
struct student {
int id;
char name[10];
int score;
} stu[100005];
由题目可知我们要写三个cmp函数
分别如下:
bool cmp1(struct student a, struct student b) {
return a.id < b.id; //按学号递增排序
}
bool cmp2(struct student a, struct student b) {
//按姓名的非递减字典序排序(即递增序列)
if (strcmp(a.name, b.name)) return strcmp(a.name, b.name) < 0;
else return a.id < b.id;
}
bool cmp3(struct student a, struct student b) {
if (a.score != b.score) return a.score < b.score; //按成绩的递增排序
else return a.id < b.id;
}
总的代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct student
{
int id;
char name[20];
int score;
}stu[100055];
bool cmp1(struct student a, struct student b) {
return a.id < b.id; //按学号递增排序
}
bool cmp2(struct student a, struct student b) {
//按姓名的非递减字典序排序
if (strcmp(a.name, b.name)) return strcmp(a.name, b.name) < 0;
else return a.id < b.id;
}
bool cmp3(struct student a, struct student b) {
if (a.score != b.score) return a.score < b.score; //按成绩的递增排序
else return a.id < b.id;
}
int main(void)
{
int N,C;
int i;
int number=1;
while(1)
{
scanf("%d %d",&N,&C);
if(N==0)
return 0;
for(i=0;i<N;i++)
{
scanf("%d %s %d",&stu[i].id,stu[i].name,&stu[i].score);
}
switch(C)
{
case 1:
sort(stu,stu+N,cmp1);
break;
case 2:
sort(stu,stu+N,cmp2);
break;
case 3:
sort(stu,stu+N,cmp3);
break;
}
printf("Case %d:\n",number++);
for(i=0;i<N;i++)
{
printf("%06d %s %d\n",stu[i].id,stu[i].name,stu[i].score);
}
}
return 0;
}
字符串内排序
-
题目描述
输入一个字符串,长度小于等于200,然后将输出按字符顺序升序排序后的字符串。 -
输入
测试数据有多组,输入字符串。 -
输出
对于每组输入,输出处理后的结果。 -
样例输入
tianqin
- 样例输出
aiinnqt
提示 :注意输入的字符串中可能有空格。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int main() {
char s[300];
while (gets(s))
{
sort(s, s + strlen(s));
puts(s);
}
return 0;
}
Problem B
-
题目描述
请写一个程序,对于一个m行m列的(1<m<10)的方阵,求其每一行,每一列及主对角线元素之和,最后按照从大到小的顺序依次输出。 -
输入
共一组数据,输入的第一行为一个正整数,表示m,接下来的m行,每行m个整数表示方阵元素。 -
输出
从大到小排列的一行整数,每个整数后跟一个空格,最后换行。 -
样例输入
4
15 8 -2 6
31 24 18 71
-3 -9 27 13
17 21 38 69
- 样例输出
159 145 144 135 81 60 44 32 28 27
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int a[40];
int b[12][12];
bool cmp(int a,int b)
{
return a>b;
}
int main(void)
{
int m,i,j;
int num=0;
while( scanf("%d",&m) != EOF )
{
num=0;
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",&b[i][j]);
a[num]+=b[i][j]; //求各个行的和
}
num++;
}
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
a[num]+=b[j][i];//求各个列的和
}
num++;
}
for(i=0;i<m;i++)
{
a[num]+=b[i][i];//左对角线和
a[num+1]+=b[m-1-i][i];//右对角线和
}
num=num+1;//最后一个数的地址
num=num+1;//最后一个数的下一个地址
sort(a,a+num,cmp);
for(i=0;i<num;i++)
{
printf("%d ",a[i]);
a[i]=0;//重新初始化
}
printf("\n");
}
return 0;
}
进一步的优化算法
#include <cstdio>
#include <algorithm>
using namespace std;
bool cmp(int a, int b) {
return a > b;
}
int matrix[12][12];
int r[30];
int main() {
int m;
while (scanf("%d", &m) != EOF) {
int len = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
scanf("%d", &matrix[i][j]);
}
}
//每一行与列求和
for (int i = 0; i < m; i++) {
int Rsum = 0, Csum = 0;
for (int j = 0; j < m; j++) {
Rsum += matrix[i][j];
Csum += matrix[j][i];
}
r[len++] = Rsum;
r[len++] = Csum;
}
//主次对角线求和
int LDsum = 0, RDsum = 0;
for (int i = 0; i < m; i++) {
LDsum += matrix[i][i];
RDsum += matrix[i][m - i - 1];
}
r[len++] = LDsum;
r[len++] = RDsum;
sort(r, r + len, cmp);
for (int i = 0; i < len - 1; i++) {
printf("%d ", r[i]);
}
printf("%d\n", r[len - 1]);
}
return 0;
}
这个算法相比上一个简便了不少。
一组结束后不用再次的初始化。
小白鼠排队
-
题目描述
N只小白鼠(1 <= N <= 100),每只鼠头上戴着一顶有颜色的帽子。现在称出每只白鼠的重量,要求按照白鼠重量从大到小的顺序输出它们头上帽子的颜色。帽子的颜色用“red”,“blue”等字符串来表示。不同的小白鼠可以戴相同颜色的帽子。白鼠的重量用整数表示。 -
输入
多案例输入,每个案例的输入第一行为一个整数N,表示小白鼠的数目。
下面有N行,每行是一只白鼠的信息。第一个为不大于100的正整数,表示白鼠的重量;第二个为字符串,表示白鼠的帽子颜色,字符串长度不超过10个字符。
注意:白鼠的重量各不相同。 -
输出
每个案例按照白鼠的重量从大到小的顺序输出白鼠的帽子颜色。 -
样例输入
1
79 omi
9
46 lcg
92 cru
37 ceq
54 vhr
17 wus
27 tnv
13 kyr
95 wld
34 qox
- 样例输出
omi
wld
cru
vhr
lcg
ceq
qox
tnv
wus
kyr
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct mouse
{
int weight;//重量
char color[15]; //颜色
} m[105];
bool cmp(mouse a,mouse b)
{
return a.weight>b.weight;
}
int main(void)
{
int n,i;
while( scanf("%d",&n) != EOF )
{
for(i=0;i<n;i++)
{
scanf("%d %s",&m[i].weight,m[i].color);
}
sort(m,m+n,cmp);
for(i=0;i<n;i++)
{
printf("%s\n",m[i].color);
}
}
return 0;
}
排名
-
题目描述
今天的上机考试虽然有实时的Ranklist,但上面的排名只是根据完成的题数排序,没有考虑每题的分值,所以并不是最后的排名。给定录取分数线,请你写程序找出最后通过分数线的考生,并将他们的成绩按降序打印。 -
输入
测试输入包含若干场考试的信息。每场考试信息的第1行给出考生人数N ( 0 < N < 1000 )、考题数M ( 0 < M < = 10 )、分数线(正整数)G;第2行排序给出第1题至第M题的正整数分值;以下N行,每行给出一名考生的准考证号(长度不超过20的字符串)、该生解决的题目总数m、以及这m道题的题号(题目号由1到M)。
当读入的考生人数为0时,输入结束,该场考试不予处理。 -
输出
对每场考试,首先在第1行输出不低于分数线的考生人数n,随后n行按分数从高到低输出上线考生的考号与分数,其间用1空格分隔。若有多名考生分数相同,则按他们考号的升序输出。 -
样例输入
3 5 32
17 10 12 9 15
CS22003 5 1 2 3 4 5
CS22004 3 5 1 3
CS22002 2 1 5
0
- 样例输出
3
CS22003 63
CS22004 44
CS22002 32
- 提示
这题比较简单,计算好每个人的分数后按题目要求排序即可。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct student
{
char id[10];
int sum;
}s[1005];
bool cmp(student a,student b)
{
if(a.sum!=b.sum)
return a.sum>b.sum;
else
return strcmp(a.id,b.id)<0;
}
int main(void)
{
int n,m,g;
int i,j;
int k;//做对的题目数
int choice;//作对的题号
int b[1005]={
};//每道题对应的分数
int num=0;//统计过线的人数
while(1)
{
scanf("%d",&n);
num=0;
if(n==0)
return 0;
scanf("%d %d",&m,&g);
for(i=1;i<=m;i++)
{
scanf("%d",&b[i]);
}
for(i=0;i<n;i++)
{
scanf("%s",s[i].id);
scanf("%d",&k);
for(j=1;j<=k;j++)
{
scanf("%d",&choice);
s[i].sum+=b[choice];//统计总分
}
if(s[i].sum>=g)//统计过线的人数
num++;
}
sort(s,s+n,cmp);
printf("%d\n",num);
for(i=0;i<n;i++)
{
if(s[i].sum>=g)
printf("%s %d\n",s[i].id,s[i].sum);
}
}
return 0;
}
将学金
链接:https://ac.nowcoder.com/acm/problem/16639
来源:牛客网
- 题目描述
某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学 排在前面,这样,每个学生的排序是唯一确定的。
任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前五名名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分) 是:
7 279
5 279
这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是 279 (总分等于输入的语文、数学、英语三科成绩之和) ,但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是:
5 279
7 279
则按输出错误处理,不能得分。 - 输入描述:
第1行为一个正整数n,表示该校参加评选的学生人数。
第2到n+1行,每行有3个用空格隔开的数字,每个数字都在O到100之间z第1行的3个数 字依次表示学号为j-1的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为l~n (恰好是输入数据的行号减1)。
所给的数据都是正确的,不必检验。
输出描述:
共有5行,每行是两个用空格隔开的正整数,依次表示前5名学生的学号和总分。
示例1
输入
6
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98
输出
6 265
4 264
3 258
2 244
1 237
示例2
输入
8
80 89 89
88 98 78
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98
输出
8 265
2 264
6 264
1 258
5 258
备注:
50%的数据满足: 各学生的总成绩各不相同
100%的数据满足: 6 ≤ n ≤ 300
#include<cstdio>
#include<algorithm>
using namespace std;
struct student
{
int chinese;
int math;
int english;
int sum;
int id;
}s[305];
bool cmp(student a,student b)
{
if(a.sum!=b.sum)
{
return a.sum>b.sum;
}
else
{
if(a.chinese!=b.chinese)
return a.chinese>b.chinese;
else
return a.id<b.id;
}
}
int main(void)
{
int n;
int i;
while( scanf("%d",&n) != EOF )
{
for(i=0;i<n;i++)
{
scanf("%d %d %d",&s[i].&chinese,s[i].math,&s[i].english);
s[i].sum=s[i].chinese+s[i].math+s[i].english;
s[i].id=i+1;
}
sort(s,s+n,cmp);
for(i=0;i<5;i++)
{
printf("%d %d\n",s[i].id,s[i].sum);
}
}
return 0;
}
分数线划定
链接:https://ac.nowcoder.com/acm/problem/16625
来源:牛客网
- 题目描述
世博会志愿者的选拔工作正在 A 市如火如荼的进行。为了选拔最合适的人才,A 市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的150%划定,即如果计划录取m名志愿者,则面试分数线为排名第m*150%(向下取整)名的选手的分数,而最终进入面试的选手为笔试成绩不低于面试分数线的所有选手。
现在就请你编写程序划定面试分数线,并输出所有进入面试的选手的报名号和笔试成绩。 - 输入描述:
第一行,两个整数n,m(5≤n≤5000,3≤m≤n),中间用一个空格隔开,其中n 表示报名参加笔试的选手总数,m表示计划录取的志愿者人数。输入数据保证m*150%向下取整后小于等于n。
第二行到第n+1行,每行包括两个整数,中间用一个空格隔开,分别是选手的报名号k(1000≤k≤9999)和该选手的笔试成绩s(1≤s≤100)。数据保证选手的报名号各不相同。 - 输出描述:
第一行,有两个整数,用一个空格隔开,第一个整数表示面试分数线;第二个整数为进入面试的选手的实际人数。
从第二行开始,每行包含两个整数,中间用一个空格隔开,分别表示进入面试的选手的报名号和笔试成绩,按照笔试成绩从高到低输出,如果成绩相同,则按报名号由小到大的顺序输出。
示例1
输入
6 3
9848 90
6731 88
1422 95
7483 84
8805 95
4162 88
输出
88 5
1422 95
8805 95
9848 90
4162 88
6731 88
说明
m150% = 3150% = 4.5,向下取整后为 4。保证4个人进入面试的分数线为88,但因为88有重分,
所以所有成绩大于等于 88 的选手都可以进入面试,故最终有 5 个人进入面试。
#include<cstdio>
#include<algorithm>
using namespace std;
struct student
{
int sum;//分数
int id;//学号
}s[5005];
bool cmp(student a,student b)
{
if(a.sum!=b.sum)
return a.sum>b.sum;
else
return a.id<b.id;
}
int main(void)
{
int n,m;//n代表总的人数 m代表志愿者人数
int end_number;//进入面试的人数
int end_score;//面试分数线
int i;
scanf("%d %d",&n,&m);
end_number=m*1.5;
for(i=0;i<n;i++)
{
scanf("%d %d",&s[i].id,&s[i].sum);
}
sort(s,s+n,cmp);//总的排序
end_score=s[end_number-1].sum;//面试的分数线
for(i=end_number;i<n;i++)//加上重分的人
{
if(s[i].sum==end_score)
end_number++;
else
break;
}
printf("%d %d",end_score,end_number);
for(i=0;i<end_number;i++)
{
printf("%d %d\n",s[i].id,s[i].sum);
}
return 0;
}
统计数字
链接:https://ac.nowcoder.com/acm/problem/16643
来源:牛客网
- 题目描述
某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。 - 输入描述:
第1行是整数n,表示自然数的个数。
第2~n+1行每行一个自然数。 - 输出描述:
输出m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。
示例1
输入
8
2
4
2
4
5
100
2
100
输出
2 3
4 2
5 1
100 2
备注:
40%的数据满足:1 ≤ n ≤ 1000
80%的数据满足:1 ≤ n ≤ 50000
100%的数据满足:1 ≤ n ≤ 200000,每个数均不超过1500000000(1.5*109)
#include<stdio.h>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
struct num
{
int score;//数的大小
int n;//次数
}s[200005];
bool cmp(num a,num b)
{
return a.score<b.score;
}
int main(void)
{
int n;
int i,j;
int a;
int temp=0;
int w=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
w=0;//判断是否重复
if(i==1)
{
scanf("%d",&s[0].score);
s[0].n=s[0].n+1;
temp++;
continue;
}
scanf("%d",&a);
for(j=0;j<temp;j++)
{
if(s[j].score==a)
{
s[j].n=s[j].n+1;
w=1;//重复了
break;
}
}
if(!w)
{
s[temp].score=a;
s[temp].n++;
temp++;
}
}
sort(s,s+temp,cmp);
for(j=0;j<temp;j++)
{
printf("%d %d\n",s[j].score,s[j].n);
}
return 0;
}
拼数【★★】
链接:https://ac.nowcoder.com/acm/problem/16783
来源:牛客网
- 题目描述
设有n个正整数(n ≤ 20),将它们联接成一排,组成一个最大的多位整数。
例如:n=3时,3个整数13,312,343联接成的最大整数为:34331213
又如:n=4时,4个整数7,13,4,246联接成的最大整数为:7424613 - 输入描述:
第一行,一个正整数n。
第二行,n个正整数。 - 输出描述:
一个正整数,表示最大的整数
示例1
输入
3
13 312 343
输出
34331213
解题思路
先把整数化成字符串,然后再比较a+b和b+a,如果a+b>b+a,就把a排在b的前面,反之则把a排在b的后面,最后输出排序后的字符串,即可得到最大的整数(如果求最小的整数,则从小到大排序)。
举例说明:a=‘123’,b=‘71’,a+b=‘12371’,b+a=‘71123’,所以a+b<b+a,将b排在前面
注意:正常的字符串存在比较缺陷,如:A=’321’,B=’32’,按照标准的字符串比较规则因为A>B,所以A+B > B+A ,而实际上’32132’ < ’32321’。
具体步骤如下:
1.获取n
2.依次获取n个正整数,将整数转换为字符串:声明字符串数组a[n],将获取到的正整数存入数组a中,即可实现正整数到字符串的转换
3.自定义排序函数:如果a+b>b+a,则把a排在前面,否则将b排在前面(对于字符串a、b,a+b表示连接两个字符串形成一个新串)
4.从大到小输出排序后的字符串即可得到最大的整数。
每一个单独的小部分能组成最大的整数时,这个整体就能组成最大的整数
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
bool cmp(string a,string b)
{
return a+b>b+a;//如果a+b>b+a,则把a排在前面,否则将b排在前面
}
int main(void)
{
string a[21];
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n,cmp);
for(int i=0;i<n;i++)
{
cout<<a[i];
}
return 0;
}
图书管理员【★★】
链接:https://ac.nowcoder.com/acm/problem/16422
来源:牛客网
-
题目描述
图书馆中每本书都有一个图书编码,可以用于快速检索图书,这个图书编码是一个正整数。
每位借书的读者手中有一个需求码,这个需求码也是一个正整数。如果一本书的图书编码恰好以读者的需求码结尾,那么这本书就是这位读者所需要的。
小 D 刚刚当上图书馆的管理员,她知道图书馆里所有书的图书编码,她请你帮她写一个程序,对于每一位读者,求出他所需要的书中图书编码最小的那本书,如果没有他需要的书,请输出-1。 -
输入描述:
输入的第一行,包含两个正整数 n 和 q,以一个空格分开,分别代表图书馆里书的数量和读者的数量。
接下来的 n 行,每行包含一个正整数,代表图书馆里某本书的图书编码。
接下来的 q 行,每行包含两个正整数,以一个空格分开,第一个正整数代表图书馆里读者的需求码的长度,第二个正整数代表读者的需求码。 -
输出描述:
输出有 q 行,每行包含一个整数,如果存在第 i 个读者所需要的书,则在第 i 行输出第 i 个读者所需要的书中图书编码最小的那本书的图书编码,否则输出-1。
示例1
输入
5 5
2123
1123
23
24
24
2 23
3 123
3 124
2 12
2 12
输出
23
1123
-1
-1
-1
说明
第一位读者需要的书有 2123、1123、23,其中 23 是最小的图书编码。
第二位读者需要的书有 2123、1123,其中 1123 是最小的图书编码。
对于第三位,第四位和第五位读者,没有书的图书编码以他们的需求码结尾,即没有他们需要的书,输出-1。
题目分析:
本题的难点在于如何找子串。
23 结尾的 2123如何找到 ?是问题的关键。
你分析一下:
(2123 -23)%100==0
(23-23)%100==0
(1123-23)%100==0
(1123-123)%1000==0
综上所述:
你会发现我们要找的图书满足以下条件:
(图书编码-需求码)%10需求码的位数==0
#include<cstdio>
#include<algorithm>
using namespace std;
int book[1005];
int pow(int a)
{
int n=1;
while(a)
{
n=n*10;
a=a/10;
}
return n;
}
int main(void)
{
int n,q;
int i,j;
int m,number;
int flag=0;//判断是否找到书
scanf("%d %d",&n,&q);
for(i=0;i<n;i++)
{
scanf("%d",&book[i]);
}
sort(book,book+n);//排序后,方便查找。首次满足条件的就是最小的
for(i=0;i<q;i++)
{
flag=0;
scanf("%d %d",&m,&number);
for(j=0;j<n;j++)
{
if( (book[j]-number)%pow(number)==0)//判断有没有
{
printf("%d\n",book[j]);
flag=1;
break;
}
}
if(!flag)
{
printf("-1\n");
}
}
return 0;
}
1025 PAT Ranking 【★★★】
编程能力测试(PAT)由浙江大学计算机科学与技术学院组织。每个测试应该在多个地方同时运行,并且等级列表将在测试后立即合并。现在,您的工作就是编写一个程序来正确合并所有排名列表并生成最终排名。
-
输入规格:
每个输入文件包含一个测试用例。对于每种情况,第一行都包含一个正数ñ (≤100),测试位置的数量。然后ñ 等级列表紧随其后,每个列表均以包含正整数的行开头 到 (≤300),受测试者的数量,然后 到每行包含注册号(13位数字)和每个考生的总分。一行中的所有数字都用空格分隔。 -
输出规格:
对于每个测试用例,首先在一行中打印被测试者的总数。然后以以下格式打印最终排名列表:
registration_number final_rank location_number local_rank
位置编号从1到 ñ。必须按照最终排名的降序对输出进行排序。具有相同分数的被测者必须具有相同的等级,并且输出必须以其注册号的降序排列。
输入样例:
2
5
1234567890001 95
1234567890005 100
1234567890003 95
1234567890002 77
1234567890004 85
4
1234567890013 65
1234567890011 25
1234567890014 100
1234567890012 85
样本输出:
9
1234567890005 1 1 1
1234567890014 1 2 1
1234567890001 3 1 2
1234567890003 3 1 2
1234567890004 5 1 4
1234567890012 5 2 2
1234567890002 7 1 5
1234567890013 8 2 3
1234567890011 9 2 4
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>>
using namespace std;
struct student
{
char id[13];//准考证号
int score;//分数
int location_number;//考场号
int local_rank; //考场内排名
}stu[30005];
bool cmp(student s1,student s2)
{
if(s1.score!=s2.score)
return s1.score>s2.score;//先按分数从高到低排
else
return strcmp(s1.id,s2.id)<0;//分数相同则按照准考证号从小到大排。
}
int main(void)
{
int n,k,num=0;//num为总的考生数
int i,j;
scanf("%d",&n);//n为考场数
for(i=1;i<=n;i++)
{
scanf("%d",&k);//该考场内的人数
for(j=0;j<k;j++)
{
scanf("%s %d",stu[num].id,&stu[num].score);
stu[num].location_number=i;//该考生的考场号为i
num++;//总考生数加1
}
sort(stu+num-k,stu+num,cmp);//将该考场的考生排序
stu[num-k].local_rank=1;//该考场第一名的local_rank记为1
for(j=num-k+1;j<num;j++)//对该考场剩余的学生
{
if(stu[j].score==stu[j-1].score)//如果与前一位同学分数相同,则local_rank也相同
{
stu[j].local_rank=stu[j-1].local_rank;
}
else
{
//local_rank代表的是该考生(包括自己)前的人数
// 1 1 3 4 5
// 1 2 3 4 5
stu[j].local_rank=j+1-(num-k);
//j+1代表包括了自己 num-k是第一个考生的编号
}
}
}
printf("%d\n",num);//输出总的考生个数
sort(stu,stu+num,cmp);//将所有考生排序
int r=1;//考生在总考生中的排名
for(i=0;i<num;i++)
{
if(i>0&&stu[i].score!=stu[i-1].score)
{
r=i+1;
}
printf("%s ",stu[i].id);
printf("%d %d %d\n",r,stu[i].location_number,stu[i].local_rank);
}
return 0;
}