1、知识点:排序
2、思路:定义course结构、student结构:
struct course{
int ind, stu_num; //课程编号,选课学生数
char name_arr[MAXNI][STRLEN]; //学生姓名
};
struct student{
int order; //查询顺序
char name[STRLEN]; //姓名
vector course_ind; //课程编号
};
读入课程数组cour,然后按ind排序;读入查询学生数组stu_arr,按姓名排序。然后遍历课程,对于每门课的每个选课学生,按照二分查找查询学生表stu_arr中的姓名,如果找到,就将对应的课程编号加入该学生。最后将查询学生表stu_arr做数据离散化,映射到disc数组,遍历disc数组打印输出答案。
注意:
①尽量用C的内容而不是C++(代码换成C++版超时,而C版顺利AC,~~);
②学生姓名排好序按照二分查找提升效率,否则会超时;
③student结构中用了vector,如果用malloc分配内存会出错,直接定义stu_arr数组或者用new分配内存则没事。
/*用途:
**说明:
**算法:
*/
//#define LOCAL
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define MAXN 40000+10
#define MAXK 2500+10
#define MAXNI 200+10
#define STRLEN 10
struct student{
int order;
char name[STRLEN];
vector<int> course_ind;
};
struct course{
int ind, stu_num;
char name_arr[MAXNI][STRLEN];
};
int N, K;
course *cour;
//student stu_arr[MAXN];
student *stu_arr;
int *disc; //stu_arr的离散化数组
void init_course();
int cmp_course_ind(const void* a, const void* b);
void init_stu();
int cmp_order(const void* a, const void* b);
int find_name(char* name); //二分查找姓名
void print_course_ind(int ind);
int main()
{
#ifdef LOCAL
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
#endif
scanf("%d%d", &N, &K);
cour = (course*)malloc(sizeof(course)*K);
init_course();
for(int i=0; i<K; i++){
int ind, stu_num;
char name[STRLEN];
scanf("%d%d", &ind, &stu_num);
for(int j=0; j<stu_num; j++){
scanf("%s", name);
cour[i].ind = ind;
strcpy(cour[i].name_arr[cour[i].stu_num], name);
cour[i].stu_num++;
}
}
qsort(cour, K, sizeof(course), cmp_course_ind);
// stu_arr = (student*)malloc(sizeof(student)*N); //出错
stu_arr = new student[N];
for(int i=0; i<N; i++){
scanf("%s", stu_arr[i].name);
stu_arr[i].order = i;
}
qsort(stu_arr, N, sizeof(student), cmp_order);
int index;
char name[STRLEN];
for(int i=0; i<K; i++){
for(int j=0; j<cour[i].stu_num; j++){
index = find_name(cour[i].name_arr[j]);
if(index != -1)
stu_arr[index].course_ind.push_back(cour[i].ind);
}
}
disc = new int[N];
for(int i=0; i<N; i++)
disc[stu_arr[i].order] = i;
for(int i=0; i<N; i++){
int ind = disc[i];
printf("%s %d", stu_arr[ind].name, stu_arr[ind].course_ind.size());
print_course_ind(ind);
}
return 0;
}
void init_course()
{
for(int i=0; i<K; i++)
cour[i].ind = cour[i].stu_num = 0;
}
void print_course_ind(int ind)
{
int len = stu_arr[ind].course_ind.size();
for(int i=0; i<len; i++)
printf(" %d", stu_arr[ind].course_ind[i]);
printf("\n");
}
inline int cmp_course_ind(const void* a, const void* b)
{
return (*(course*)a).ind - (*(course*)b).ind;
}
inline int cmp_order(const void* a, const void* b)
{
return strcmp((*(student*)a).name, (*(student*)b).name) < 0 ? -1 : 1; //注意这里的比较字符数组的方法
}
inline int find_name(char* name)
{
int start, med, end;
start = 0;
end = N-1;
med = (start + end) / 2;
while(start <= end){
if(strcmp(name, stu_arr[med].name) > 0)
start = med+1;
else if(!strcmp(name, stu_arr[med].name))
return med;
else
end = med-1;
med = (start + end) / 2;
}
return -1;
}