目录

  • 6.1 vector的常见用法详解
    • 问题 A: Course List for Student (25)
    • 问题 B: Student List for Course (25)
    • 小结

6.1 vector的常见用法详解

Codeup Contest ID:100000596

问题 A: Course List for Student (25)

题目描述
Zhejiang University has 40000 students and provides 2500 courses. Now given the student name lists of all the courses, you are supposed to output the registered course list for each student who comes for a query.
输入
Each input file contains one test case. For each case, the first line contains 2 positive integers: N (<=40000), the number of students who look for their course lists, and K (<=2500), the total number of courses. Then the student name lists are given for the courses (numbered from 1 to K) in the following format: for each course i, first the course index i and the number of registered students Ni (<= 200) are given in a line. Then in the next line, Ni student names are given. A student name consists of 3 capital English letters plus a one-digit number. Finally the last line contains the N names of students who come for a query. All the names and numbers in a line are separated by a space.
输出
For each test case, print your results in N lines. Each line corresponds to one student, in the following format: first print the student’s name, then the total number of registered courses of that student, and finally the indices of the courses in increasing order. The query results must be printed in the same order as input. All the data in a line must be separated by a space, with no extra space at the end of the line.
样例输入

11 5
4 7
BOB5 DON2 FRA8 JAY9 KAT3 LOR6 ZOE1
1 4
ANN0 BOB5 JAY9 LOR6
2 7
ANN0 BOB5 FRA8 JAY9 JOE4 KAT3 LOR6
3 1
BOB5
5 9
AMY7 ANN0 BOB5 DON2 FRA8 JAY9 KAT3 LOR6 ZOE1
ZOE1 ANN0 BOB5 JOE4 JAY9 FRA8 DON2 AMY7 KAT3 LOR6 NON9

样例输出

ZOE1 2 4 5
ANN0 3 1 2 5
BOB5 5 1 2 3 4 5
JOE4 1 2
JAY9 4 1 2 4 5
FRA8 3 2 4 5
DON2 2 4 5
AMY7 1 5
KAT3 3 2 4 5
LOR6 4 1 2 4 5
NON9 0

思路
这题的大致意思是:N是要查询的学生人数,K是课的数目,然后有K行,每行给出一个课的编号i,和要上这门课的学生人数Ni,然后下一行是要上这门课的学生名字。

最直观的思路就是像题目一样把输入的每行学生名字都存在一个二维数组里,行号代表课的编号,每一列就是一堆学生名字(用结构体)。最后把名单存储在一个字符串数组里,然后再通过for循环查找名单里每一个学生(O(N)),再查找每行(O(K))的每一个学生(O(Ni)),判断其名字是否与待查找的学生名字相等,如果相等,则方案数cnt++,并且把当前的行号压入到暂存的temp向量中,查找完毕之后输出即可。但是,这么做时间肯定是会超限的,三重循环的查找,时间复杂度是O(N×K×Ni)=O(40000×2500×200),显然是过大的。

在这里我建议大家,有想法就去做,不要怕难,其实我一开始根据输出结果就想到用二维数组的散列来存储了,行是学生姓名,列是int型的一维散列表,但是因为害怕字符串对整数类型的hash映射(26进制或者更多的进制数转10进制的方法),所以没有做下去,换了一种O(N3)的直观方法来做,但是那样做的话也就25分里拿23分了(PAT我提交过,最后一个测试点超时),如果实在想不起来字符串的hash函数怎么写的话,就这样做好了,但是想要拿满分的话还是得牢记字符串的hash呀。

于是优化后的思路就是:开一个大小为26×26×26×10+10(3个大写字母和1个数字,因此是263×10+10)的int型vector(其实就是26×26×26×10+10个int型vector容器),行号对应学生姓名映射过来的整数型id,每一个vector里面存储的是对应那个学生要上的课的编号。然后每次输入姓名的时候就直接映射成id,把这门课的编号push_back到对应的容器里。最后根据id依次输出每个容器里的内容就行了,需要注意的是,因为压入的时候可能是大的数字在前(比如题目给的样例,先是4,再是1、2、3、5),所以vector容器里可能是乱序,因此每次准备输出这个容器里的所有元素之前,需要用sort函数给容器里的元素排序。

当然,这题你也可以用二维数组来做,行号是id,列号是所有课程的编号,因此第二维最多开到2501,每次读入一个课的编号index,就把stu[id][index]置1,然后最后遍历这一行的所有元素,输出值是1的下标即可(这么一想是不是vector要快速多了,可以免去很多无效的查询)。
代码

///直观的超时方案///
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<algorithm>
#include<vector>
using namespace std;
struct student{char name[5];student(){memset(name, 0, sizeof(name));}
};
vector<student> stu[2501];
vector<int> temp;
char name[40000][5];
int main(){int N, K;while(scanf("%d%d", &N, &K) != EOF){for(int i=1;i<=K;i++){int index, n;scanf("%d%d", &index, &n);for(int j=1;j<=n;j++){student tmp;scanf("%s", tmp.name);stu[index].push_back(tmp);}}for(int i=0;i<N;i++) scanf("%s", name[i]);for(int i=0;i<N;i++){int cnt = 0;for(int j=1;j<=K;j++){for(int k=0;k<stu[j].size();k++){if(strcmp(name[i], stu[j][k].name)==0){cnt++;temp.push_back(j);}}}printf("%s %d", name[i], cnt);for(int j=0;j<temp.size();j++) printf(" %d", temp[j]);printf("\n");temp.clear();}}return 0;
}
///优化后的代码///
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 26*26*26*10+10;//3个大写字母加1个数字
int getid(char s[], int len){//建立字符串到整数的hash int id = 0;for(int i=0;i<len-1;i++){//末尾是数字,除掉末尾id = id*26 + (s[i]-'A'); }id = id*10+(s[len-1]-'0');//把最后一位数字直接拼接上去 return id;
}
vector<int> stu[maxn];//行号是学生姓名对应的id,每一个vector容器里又包含着学生所选的课
char name[40000][5];
int main(){int N, K;while(scanf("%d%d", &N, &K) != EOF){for(int i=1;i<=K;i++){int index, n;//index是课的编号,n是选这门课的学生人数 scanf("%d%d", &index, &n);for(int j=1;j<=n;j++){char temp[5];int len = 0;scanf("%s", temp);int id = getid(temp, strlen(temp));stu[id].push_back(index);//给对应学生压入课的编号}}for(int i=0;i<N;i++) scanf("%s", name[i]);//输入待查询的学生姓名for(int i=0;i<N;i++){int id = getid(name[i], strlen(name[i]));sort(stu[id].begin(), stu[id].end());printf("%s %d", name[i], stu[id].size());for(int j=0;j<stu[id].size();j++){printf(" %d", stu[id][j]);}printf("\n");} }return 0;
}

问题 B: Student List for Course (25)

题目描述
Zhejiang University has 40000 students and provides 2500 courses. Now given the registered course list of each student, you are supposed to output the student name lists of all the courses.
输入
Each input file contains one test case. For each case, the first line contains 2 numbers: N (<=40000), the total number of students, and K (<=2500), the total number of courses. Then N lines follow, each contains a student’s name (3 capital English letters plus a one-digit number), a positive number C (<=20) which is the number of courses that this student has registered, and then followed by C course numbers. For the sake of simplicity, the courses are numbered from 1 to K.
输出
For each test case, print the student name lists of all the courses in increasing order of the course numbers. For each course, first print in one line the course number and the number of registered students, separated by a space. Then output the students’ names in alphabetical order. Each name occupies a line.
样例输入

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

思路
这一题和上一题正好倒过来,上一题是让你输出每个学生要上哪些课,这一题是让你输出每门课有哪几个学生要上。
为了方便,我这里直接用了C++里的<string>(注意,和<string.h>不是同一个东西,另外,想要输入输出整个字符串,只能用C++里的cin和cout(在<iostream>里面)),声明了里面存放字符串类型的vector,这样的话,每个vector里就能存放一个又一个学生的名字了。同样的道理,下标对应的是课程的编号,于是声明的最大值应该是2500,每次输入一个课程编号的时候,就把学生的姓名压入对应的course[tmp]中。

然而很不幸的是……以上思路的代码虽然在codeupAC了,但是PAT还是超时了(难道是cin和cout的问题??)
于是我们需要沿用上一题的思路,用数字来代替每个人的名字……
代码

///codeupAC,PAT超时///
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
using namespace std;
vector<string> course[2501];
int main(){int N, K;while(cin>>N>>K){for(int i=1;i<=N;i++){string tempName;int C;cin>>tempName>>C;for(int j=1;j<=C;j++){int tmp;cin>>tmp;course[tmp].push_back(tempName);}}for(int i=1;i<=K;i++){cout<<i<<' '<<course[i].size()<<endl;sort(course[i].begin(), course[i].end());for(int j=0;j<course[i].size();j++) cout<<course[i][j]<<endl;}} return 0;
}
///优化后的代码///
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
using namespace std;
vector<int> course[2501];
char name[40001][5];
bool cmp(int a, int b){return strcmp(name[a], name[b])<0;//字典序升序
}
int main(){int N, K;while(scanf("%d%d", &N, &K) != EOF){for(int i=1;i<=N;i++){scanf("%s", name[i]);//i号学生 int C;scanf("%d", &C);for(int j=1;j<=C;j++){int tmp;scanf("%d", &tmp);course[tmp].push_back(i);//把i号学生的i压入 }}for(int i=1;i<=K;i++){printf("%d %d\n", i, course[i].size());sort(course[i].begin(), course[i].end(), cmp);for(int j=0;j<course[i].size();j++) printf("%s\n", name[course[i][j]]);//course[i][j]是存储的几号学生,只要对应回name字符串数组即可输出对应的学生名字 } } return 0;
}

小结

初见vector可能比较受苦?(做题做出了玩黑魂的感觉hhh),虽然我一开始做问题A的时候极其抵触vector,因为用不来也理解不了,想要用二维数组去做。但是用熟练了之后可以看到vector其实是一种特别方便的数组(或者说线性表?),尤其是对于这些需要hash的题目来说,相比于普通的二维数组,查找快了太多太多(上面也说到过的,如果是普通二维数组,要输出值为1或是true的下标,则会存在大量的查找0或false的操作,时间白白浪费)。
在这里建议想要用二维的vector还是定义为:

vector<typename> Arrayname[arraySize];

这样比较好,因为如果定义为:

vector<vector<typename> >

这样子的话,其实是不便于题目上的操作的。
总的来说,通过这两题的练习,一来熟练了vector的用法,二来巩固了hash和sort的知识(sort也是可以用于vector排序的哈,非常方便~),可以说是收获颇丰了^^。

《算法笔记》学习日记——6.1 vector的常见用法详解相关推荐

  1. vector的常见用法详解

    目录 vector的定义 vector容器内元素的访问 vector常用函数 vector的常见用途 vector翻译为向量,但是这里使用"变长数组"的叫法更容易理解,也即&quo ...

  2. Jquery学习总结(2)——jQuery Ajax用法详解

    [详解]jquery ajax在web应用开发中常用,主要包括有ajax,get,post,load,getscript等这几种常用无刷新操作方法,下面来给大家介绍一下.我们首先先从最简单的方法看起. ...

  3. 算法笔记学习PAT甲级解题记录

    算法笔记学习记录 2019.06.26 float&&double 推荐全部使用double,注意区分scanf("%lf",&double1);与prin ...

  4. 笔记 | 百度飞浆AI达人创造营:深度学习模型训练和关键参数调优详解

    笔记 | 百度飞浆AI达人创造营:深度学习模型训练和关键参数调优详解 针对特定场景任务从模型选择.模型训练.超参优化.效果展示这四个方面进行模型开发. 一.模型选择 从任务类型出发,选择最合适的模型. ...

  5. Ext.Net学习笔记22:Ext.Net Tree 用法详解

    上面的图片是一个简单的树,使用Ext.Net来创建这样的树结构非常简单,代码如下: <ext:TreePanel runat="server"><Root> ...

  6. 深度学习模型训练和关键参数调优详解

    深度学习模型训练和关键参数调优详解 一.模型选择 1.回归任务 人脸关键点检测 2.分类任务 图像分类 3.场景任务 目标检测 人像分割 文字识别 二.模型训练 1.基于高层API训练模型 加载数据集 ...

  7. MybatisPlus学习(四)条件构造器Wrapper方法详解

    https://www.cnblogs.com/xianz666/p/13857733.html MybatisPlus学习(四)条件构造器Wrapper方法详解 文章目录 1.条件构造器 2.Que ...

  8. STL中map和string, vector 用法详解

    1. map 用法详解 std map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成 ...

  9. 深度学习之目标检测(十一)--DETR详解

    深度学习之目标检测(十一)-- DETR详解 目录 深度学习之目标检测(十一)-- DETR详解 1. 前言 2. DETR 框架 2.1 CNN Backbone 2.2 Transformer E ...

最新文章

  1. 为什么 ConcurrentHashMap 的读操作不需要加锁?
  2. python模拟鼠标点击和键盘输入的操作_Python模拟鼠标点击及键盘输入(PyUserInput)...
  3. oracle中join另一个表后会查询不出一些数据_阿里规定超过3张表,禁止JOIN,为何?
  4. VUEX源码学习笔记(第5~6章 共6章)
  5. 视觉SLAM十四讲学习笔记-第四讲-李代数求导与扰动模型
  6. mysql主从不同步问题_mysql主从之间不同步问题
  7. ASP数据库连接方式大全
  8. 用rest造句子_rest的用法和短语例句
  9. maven中常用jar包插件
  10. div 显示滚动条的CSS代码
  11. Ubuntu安装anaconda,tensorflow,keras,pytorch
  12. 地铁沉降观测数据分析之巧用VBA编程处理
  13. EasyUI下拉框自适应高度
  14. 6.Vue教程:http://www.jb51.net/Special/874.htm
  15. 选择商品的时候,弹不出来商品选择框
  16. 在浏览器中使用百度地图的定位服务获得经纬度
  17. TVU与纳加联合推出具备多网聚合功能的全能导播台
  18. signal 11 定位
  19. 微信活码系统/微信群二维码/活码生成系统/生成微信活码
  20. Python中的排除sort函数的参数key:a.sort(key=lambda x: x[1])是什么意思

热门文章

  1. Nginx+Tomcat实现负载均衡与动静分离
  2. java线程池理解与实践
  3. [写Bug记录] Maven出现 Library xxx has broken classes paths
  4. webpack代理 host文件 微信小程序公众号开发必配
  5. mongodb 基本介绍
  6. 索尼 LT26I刷机包 X.I.D 加入官方风格 GF A3.9.4 各方面完美
  7. 心雨中调用Discuz论坛IE6中代码出现乱码
  8. discuz服务器500错误信息,discuz论坛程序突然出现http500错误解决方案
  9. 2020扁皮筋排名_CSCC2020赛季竞赛规则
  10. AT3576 E Popping Balls——计数思路