#include <iostream>
#include <string>
#include <iomanip>
#define MAXN 10000
#define MAXK 5
#define MAXM 100000
using namespace std;
typedef struct user *User;
struct user {
int id;
int score[MAXK];
int total;
int numOfPer;
bool isShown;
bool operator< (const user& t) const { // 重载关系运算符!
if( total != t.total ) return total < t.total; // total小的在<左边
if( numOfPer != t.numOfPer ) return numOfPer < t.numOfPer;
return id > t.id;
}
};
User Info[MAXN];
void print( User U, int K ) {
cout << setw(5) << setfill('0') << U->id;
cout << " " << U->total << " ";
for( int i = 0; i < K; i++ ) {
if( U->score[i] == -2 ) cout << "-"; // -2则表示未提交过
else if( U->score[i] == -1 ) cout << "0";
else cout << U->score[i];
if( i != K-1 ) cout << " "; // 不是最后一个
else cout << endl;
}
}
int main() {
int N, K, M, pos, score, id;
int full[MAXK];
cin >> N >> K >> M;
for( int i = 0; i < N; i++ ) { // 就算没有提交也要算一个用户!
Info[i] = new user; // 重要!!
Info[i]->id = i + 1;
Info[i]->isShown = false;
Info[i]->total = Info[i]->numOfPer = 0; // 初始化
for( int j = 0; j < K; j++ )
Info[i]->score[j] = -2; // 最小的成绩是-1
}
for( int i = 0; i < K; i++ )
cin >> full[i];
for( int i = 0; i < M; i++ ) {
cin >> id >> pos >> score;
id--;
pos--;
if( score > Info[id]->score[pos] ) // 更高的分数替代原来的分数
Info[id]->score[pos] = score;
if( score != -1 ) Info[id]->isShown = true; // 有一道过编译就显示
}
for( int i = 0; i < N; i++ )
for( int j = 0; j < K; j++ )
if( Info[i]->score[j] >= 0 ) {
Info[i]->total += Info[i]->score[j];
if( Info[i]->score[j] == full[j] ) Info[i]->numOfPer++;
}
int j;
User Tmp;
for ( int i = 1; i < N; i++ ) { // 插入排序
Tmp = Info[i]; /* 取出未排序序列中的第一个元素 */
for ( j = i; j > 0 && *Info[j-1] < *Tmp; j-- ) // 重载<
Info[j] = Info[j-1]; /* 依次与已排序序列中元素比较并右移 */
Info[j] = Tmp; /* 放进合适的位置 */
}
cout << "1 "; // 保证至少有一个人会被展示(如果所有人都不能被展示, 展示id为00001的成绩)
print( Info[0], K );
int rank = 1, num = 1, last_score = Info[0]->total;
for( int i = 1; i < N; i++ ) // 考虑 全是-1而总分为0的用户 因为id更小排在 全是0而总分为0的用户 前面
if( Info[i]->isShown ) {
if( Info[i]->total != last_score ) { // 不能与[i-1]作比较, 它有可能不输出!!!
rank += num;
num = 1;
last_score = Info[i]->total; // 不相等时更新
}
else num++;
cout << rank << " ";
print( Info[i], K );
}
}
乍一看不难,实际上各种细节会让人抓狂,死磕了一晚上加一上午...
在csdn上看了很多测试点分析,个人说几点吧
- -1代表提交过但未通过编译,-2代表未提交过,总分只加大于等于0的分数,不会加负分
- 原来有得分后面再提交-1是不会覆盖的,毕竟题目也说了取最高分
- 排序的时候最好重载一下比较方法,不管是运算符还是cmp,因为要考虑到同总分的可能有很多用户,我这里用的是插入排序,可能会跃迁不止一次
- 保证至少一个人的成绩会被展示(所有人都不符合展示条件时展示id为00001的成绩)
- 重复提交满分不要重复增加满分次数(通过只取更高分解决)
- rank也有一个小难点,要注意到并不是所有用户都会被展示,中间可能断层