1039 Course List for Student

刚开始想的就是用hashSet来实现,幸亏看了ref:

http://tech-wonderland.net/blog/pat-1039-course-list-for-student.html

 才知道这种思路是不行的

#include <stdio.h>
#include <vector>
#include <algorithm>
#define ts1 26*26*26//把学生name视为一个26进制的数字
#define ts2 26*26
#define ts3 26
using namespace std;

vector<int> res;//按照学生姓名顺序,存储各学生的课程

int n,k;

int binaSearch(int val){
	int low = 0;
	int high = res.size()-1;

	//while(low <= high){
	//	int mid = (low+high)/2;
	//	if(val < res[mid]){
	//		high = mid - 1;
	//	}else{			//找到时,同样把low增加!
	//		low = mid + 1;
	//	}
	//}
	//return high;
	while(low<=high){
		int mid = (low+high)/2;
		if(res[mid] == val){
			return mid;
		}else if(res[mid] > val){
			high = mid-1;
		}else if(res[mid] < val){
			low = mid+1;
		}
	}
	return high;//找不到时返回high,  要找得val值在high的右边
}


int main(){
	freopen("in.txt","r",stdin);

	scanf("%d%d",&n,&k);
	char name[5];
	int cid, stuCnt;
	for(int i = 0; i < k; i++){
		scanf("%d%d",&cid,&stuCnt);
		
		for(int j = 0; j < stuCnt; j++){
			scanf("%s",&name);
			int sid = (name[0]-'A')*ts1 + (name[1]-'A')*ts2 + (name[2]-'A')*ts3 + (name[3]-'0');
			int val = sid*2500 + cid - 1;//最多有2500门课,即cid范围为[1,2500]		
								//val/2500部分是sid, val%2500是cid,为了取余数方便,将cid减1
								//则对于一个学生,特定的sid, 其val取值范围是[sid*2500, sid*2500+2499]
								//一个val代表一个<学生,课程>键值对
			res.push_back(val);
		}
	}

	//将res排序,以便进行二分查找,同时,也对同一个学生的课程进行了排序
	sort(res.begin(),res.end());

	while(scanf("%s",&name)!=EOF){
		int sid = (name[0]-'A')*ts1 + (name[1]-'A')*ts2 + (name[2]-'A')*ts3 + (name[3]-'0');
		int bottom = sid*2500-1;
		int top = sid*2500+2499;

		int s = binaSearch(bottom);//找到的s右边一个才是当前学生的第一门课程
		int e = binaSearch(top);

		printf("%s ",name);
		//不需要先保存,再统计课程个数,因为s到e的个数就是,课程是[s+1,...,e]
		printf("%d",e-s);
		 
		
		s++;
		for(int i = s; i<=e; i++){//注意是[s,e],闭区间
				printf(" %d",res[i]%2500+1);//储存cid时减1了,现在还原
		}
		printf("\n");

	}

	return 0;
}


你可能感兴趣的:(1039 Course List for Student)