PAT Basic 1095 解码PAT准考证

 PAT Basic 1001~1090请见我的github:PAT(Basic)1001~1090


1095 解码PAT准考证 (25 分)

PAT 准考证号由 4 部分组成:

  • 第 1 位是级别,即 T 代表顶级;A 代表甲级;B 代表乙级;
  • 第 2~4 位是考场编号,范围从 101 到 999;
  • 第 5~10 位是考试日期,格式为年、月、日顺次各占 2 位;
  • 最后 11~13 位是考生编号,范围从 000 到 999。

现给定一系列考生的准考证号和他们的成绩,请你按照要求输出各种统计信息。

输入格式:

输入首先在一行中给出两个正整数 N(≤10​4​​)和 M(≤100),分别为考生人数和统计要求的个数。

接下来 N 行,每行给出一个考生的准考证号和其分数(在区间 [0,100] 内的整数),其间以空格分隔。

考生信息之后,再给出 M 行,每行给出一个统计要求,格式为:类型 指令,其中

  • 类型 为 1 表示要求按分数非升序输出某个指定级别的考生的成绩,对应的 指令 则给出代表指定级别的字母;
  • 类型 为 2 表示要求将某指定考场的考生人数和总分统计输出,对应的 指令 则给出指定考场的编号;
  • 类型 为 3 表示要求将某指定日期的考生人数分考场统计输出,对应的 指令 则给出指定日期,格式与准考证上日期相同。

输出格式:

对每项统计要求,首先在一行中输出 Case #: 要求,其中 # 是该项要求的编号,从 1 开始;要求 即复制输入给出的要求。随后输出相应的统计结果:

  • 类型 为 1 的指令,输出格式与输入的考生信息格式相同,即 准考证号 成绩。对于分数并列的考生,按其准考证号的字典序递增输出(题目保证无重复准考证号);
  • 类型 为 2 的指令,按 人数 总分 的格式输出;
  • 类型 为 3 的指令,输出按人数非递增顺序,格式为 考场编号 总人数。若人数并列则按考场编号递增顺序输出。

如果查询结果为空,则输出 NA

输入样例:

8 4
B123180908127 99
B102180908003 86
A112180318002 98
T107150310127 62
A107180908108 100
T123180908010 78
B112160918035 88
A107180908021 98
1 A
2 107
3 180908
2 999

输出样例:

Case 1: 1 A
A107180908108 100
A107180908021 98
A112180318002 98
Case 2: 2 107
3 260
Case 3: 3 180908
107 2
123 2
102 1
Case 4: 2 999
NA

 

本题主要坑点在于测试点3会运行超时,因此采用二维map代替二维数组、采用unordered_map来代替map、在判断前进行 case1和case3的排序等优化操作。

具体解释见注释。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<unordered_map>
using namespace std;

struct student {
	string studentNo;
	int grade;
	student() {}
	student(string s, int g) :studentNo(s), grade(g) {}
};

struct totalStAndGradeOf1Room {
	int people_num = 0;
	int total_grade = 0;
	totalStAndGradeOf1Room() {}
};

bool cmpCase1(const student &s1, const student &s2) {
	if (s1.grade == s2.grade)
		return s1.studentNo < s2.studentNo;
	else
		return s1.grade > s2.grade;
}

bool cmpCase3(const pair<string, int> &r1, const pair<string, int> &r2) {
	if (r1.second == r2.second)
		return r1.first < r2.first;
	else
		return r1.second > r2.second;
}

void case1Print(const vector<student> &students) {
	if (students.size() == 0) {
		cout << "NA" << endl;
		return;
	}
	for (auto iter = students.cbegin(); iter != students.cend(); ++iter)
		cout << iter->studentNo << " " << iter->grade << endl;
}

void case1Select(const char &level, const vector<vector<student>> &studentsOf3Level) {
	switch (level) {
	case 'T':
		case1Print(studentsOf3Level[0]);
		break;
	case 'A':
		case1Print(studentsOf3Level[1]);
		break;
	case 'B':
		case1Print(studentsOf3Level[2]);
		break;
	default:
		//若输入的level不存在,打印“NA”
		cout << "NA" << endl;
		break;
	}
}

void case2Select(const string &room, const unordered_map<string, totalStAndGradeOf1Room> &rooms) {
	try {
		cout << rooms.at(room).people_num << " " << rooms.at(room).total_grade << endl;
	}
	catch (out_of_range) {
		cout << "NA" << endl;
	}
}

void case3Select(const string &date, const unordered_map<string, vector<pair<string, int>>> &dates) {
	try {
		if(dates.at(date).size()==0)
			cout << "NA" << endl;
		else
			for (auto iter = dates.at(date).begin(); iter != dates.at(date).end(); ++iter)
				cout << iter->first << " " << iter->second << endl;
	}
	catch (out_of_range) {
		cout << "NA" << endl;
	}
}

int main() {
	//第一行输入考生人数和统计要求的个数
	int N, M;
	cin >> N >> M;

	int i;
	//接下来N行,每行给出一个准考证号和分数
	string studentNo, room, date;
	int grade;
	student tempSt;
	//vector<student> origin(N);
	//Case 1: 将三类考生分别存放在studentsOf3Level[0]、...[1]和...[2]中
	vector<vector<student>> studentsOf3Level(3);
	//Case 2: 根据考场建立map,存放考场人数和总分对象,每次累计
	unordered_map<string, totalStAndGradeOf1Room> rooms;
	//Case 3: 根据日期建立unordered_map,再在每个map中根据考场建立unordered_map,存放考生人数
	//因为考生总人数 N<=1e4,所以不需要根据考场和日期建立1e3*1e6=1e9的二维数组,
	unordered_map<string, unordered_map<string,int>> dates;

	for (i = 0; i < N; i++) {
		cin >> studentNo >> grade;
		tempSt = student(studentNo, grade);
		//Case 1
		switch (studentNo[0]) {
		case 'T':
			studentsOf3Level[0].push_back(tempSt);
			break;
		case 'A':
			studentsOf3Level[1].push_back(tempSt);
			break;
		case 'B':
			studentsOf3Level[2].push_back(tempSt);
			break;
		}

		//Case 2
		room = studentNo.substr(1, 3);
		date = studentNo.substr(4, 6);
		rooms[room].people_num++;
		rooms[room].total_grade += grade;

		//Case 3
		dates[date][room]++;
	}

	//Case 1: 按照分数非升序、分数相同时准考证增序输出
	for (i = 0; i < 3; i++)
		sort(studentsOf3Level[i].begin(), studentsOf3Level[i].end(), cmpCase1);
	//Case 3:对每个日期下的考场按照人数非升序排序
	unordered_map<string, vector<pair<string,int>>> dates_sorted;
	for (auto iter_date = dates.begin(); iter_date != dates.end(); ++iter_date) {
		for (auto iter_room = iter_date->second.begin(); iter_room != iter_date->second.end(); ++iter_room)
			dates_sorted[iter_date->first].push_back(*iter_room);
		sort(dates_sorted[iter_date->first].begin(), dates_sorted[iter_date->first].end(), cmpCase3);
	}


	//接下来M行,每行给出一个统计要求,格式为 :类型 指令
	int type;
	char command_char;
	string command_str;
	for (i = 1; i <= M; i++) {
		cin >> type;
		//打印这是第几个指令,并重复其内容
		cout << "Case " << i << ": " << type << " ";
		//指令分1、2、3三种情况
		switch (type) {
		case 1:
			cin >> command_char;
			cout << command_char << endl;
			case1Select(command_char, studentsOf3Level);
			break;
		case 2:
			cin >> command_str;
			cout << command_str << endl;
			case2Select(command_str, rooms);
			break;
		case 3:
			cin >> command_str;
			cout << command_str << endl;
			case3Select(command_str, dates_sorted);
			break;
		default:
			cout << "NA" << endl;
			break;
		}
	}

	return 0;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值