7-47 打印选课学生名单

本文讲述了在处理大规模学生选课数据时遇到的性能问题及解决方案。作者最初使用set容器实现,但由于其底层的红黑树结构导致运行超时。通过改用vector并进行排序,成功解决了效率问题。文章讨论了C++中string与printf和scanf的兼容性,并分享了调试过程中的经验教训。
摘要由CSDN通过智能技术生成

➳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容器。码呢,也非常简单,三下五除二,就三十来行。 内心感觉非常良好,小手一点

运行超时老熟人了,内心狂喜 coutcin拜拜吧(参见7-45 航空公司VIP客户查询)…不过这里有一个问题:C中的printfscanf要如何与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());
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值