➳ENTRY 假设全校有最多40000名学生和最多2500门课程。现给出每个学生的选课清单,要求输出每门课的选课学生名单。
输入格式:
输入的第一行是两个正整数:N(≤40000),为全校学生总数;K(≤2500),为总课程数。此后N行,每行包括一个学生姓名(3个大写英文字母+1位数字)、一个正整数C(≤20)代表该生所选的课程门数、随后是C个课程编号。简单起见,课程从1到K编号。
输出格式:
顺序输出课程1到K的选课学生名单。格式为:对每一门课,首先在一行中输出课程编号和选课学生总数(之间用空格分隔),之后在第二行按字典序输出学生名单,每个学生名字占一行。
输入样例:
10 5
ZOE1 2 4 5
ANN0 3 5 2 1
BOB5 5 3 4 2 1 5
JOE4 1 2
JAY9 4 1 2 5 4
FRA8 3 4 2 5
DON2 2 4 5
AMY7 1 5
KAT3 3 5 4 2
LOR6 4 2 4 1 5
输出样例:
1 4
ANN0
BOB5
JAY9
LOR6
2 7
ANN0
BOB5
FRA8
JAY9
JOE4
KAT3
LOR6
3 1
BOB5
4 7
BOB5
DON2
FRA8
JAY9
KAT3
LOR6
ZOE1
5 9
AMY7
ANN0
BOB5
DON2
FRA8
JAY9
KAT3
LOR6
ZOE1
Ω
其实这道题我不是很想写,感觉自己将背负着水文章的嫌疑,因为确实不是一般的水,但debug还是卡了半天,其中一些坎坷也可以拿出来聊一聊。 由于每一门课程的学生是不会重复的,而且最后需要按字母序输出学生名单,那么自然而然就想到了set容器。码呢,也非常简单,三下五除二,就三十来行。 内心感觉非常良好,小手一点
运行超时老熟人了,内心狂喜
cout
,cin
拜拜吧(参见7-45 航空公司VIP客户查询)…不过这里有一个问题:C中的printf
和scanf
要如何与C++的string类兼容?
string 类提供了c_str()
方法可供printf
:
printf("%s",str.c_str());
另外对于scanf
,我们需要用resize
方法先给 str
分配空间,然后再将str
的头指针传给scanf
,这与我们认识的scanf
相同:
str.resize(n);
scanf("%s",&str[0]);
小手一点,【运行超时】变成了【答案错误】?
注意到前面5个测试点都通过了,最后一个测试点的数据量拉满🤔,估计是容器的问题。于是我将
set
换成vector
,最后对每门课程的vector
进行sort
后输出,bingo!
嗯,看来用set也要节制,毕竟set的底层是用红黑树实现的,复杂度必然是要比线性容器高许多的。
🐎
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n, k, c, m;
scanf("%d %d", &n, &k);
string name;
name.resize(5);
vector<vector<string>> info(k, vector<string>());
for (int i = 0; i < n; ++i)
{
scanf("%s %d", &name[0], &c);
for (int j = 0; j < c; ++j)
{
scanf("%d", &m);
info[m - 1].push_back(name);
}
}
for (int i = 0; i < k; ++i)
{
printf("%d %d\n", i + 1, info[i].size());
sort(info[i].begin(), info[i].end());
for (auto &w: info[i])
puts(w.c_str());
}
}