详解:
分数是怎么没掉的:
1.strcmp:
一开始我是这样写的:
return strcmp(a.yx,b.yx);
学长粗略看了一下:
return strcmp(a.yx,b.yx)==-1;
后来……
return strcmp(a.yx,b.yx)==-1?1 : 0 ;//有差别吗你个二傻子?
甚至我抄别人的把char[]换成了string,日常迷信……
实际上strcmp返回的是两个字符串第一个不相等的地方的差值,比如a(上)和c(下)就会返回-2.
所以正确的姿势是
return strcmp(a.yx,b.yx)<0;
2.其他人提到了编号,我对这个的解读是:
比如给你5个人,老师划线是前三,然而这时候有两个第一,三个第三,你编号到此就结束。当你已经输出五个人的时候,因为你是按照只要名次还有没满足大于k就继续输出的原则,然而这时候后面的名次永远是0,就会出现一直打印0 0 \n的情况。那么为什么编号往后编一个就可以避免呢?因为往后是没有分数纪录的,所以此时的名次就会被置为6,于是程序遇到这个名次就可以结束了。上图为证:

0 代表mc[5],
6代表被设置名次后的mc[5].
当然另外一种方法是判断当前输出人数是否已经全部输出完了(输出了n个人)。
代码:
#include<bits/stdc++.h>
using namespace std;
#define N 100005
struct ele{
char yx[20];
int fs;
bool friend operator <(ele a,ele b)
{
if(a.fs!=b.fs)
return a.fs>b.fs;
else
return strcmp(a.yx,b.yx)<0;
}
}s[N];
int sum=0;
int n,g,k;
int main()
{
memset(s,'\0',sizeof(s));
cin>>n>>g>>k;
int i;
for(i=0;i<n;i++)
{
scanf("%s%d",s[i].yx,&s[i].fs);
if(s[i].fs>=60&&s[i].fs<g)
sum+=20;
else if(s[i].fs<=100&&s[i].fs>=g)
sum+=50;
}
cout<<sum<<endl;
sort(s,s+n);
int mc[N];
mc[0]=1;
//cout<<mc[5]<<endl;
for(i=1;i<n+1;i++)
{
if(s[i].fs==s[i-1].fs)
mc[i]=mc[i-1];
else
mc[i]=i+1;//第一种解决方法
}
//cout<<mc[5]<<endl;
int jb=0;
while(1)
{
//if(jb==n) break; 第二种解决方法
if(mc[jb]<=k)
{
printf("%d %s %d\n",mc[jb],s[jb].yx,s[jb].fs);
jb++;
}
else break;
}
return 0;
}