PAT练习笔记——4.1 排序

2019年9月PAT - 练习笔记——4.1

以下页码标注的是阅读器中实际页码,而不是书本身自印的页码。

第4章 入门篇(2)——算法初步

4.1 排序

注意

  1. 优先队列

    1. 头文件 < queue >
    2. 升序队列:priority_queue <int,vector< int >,greater< int > > q;
    3. 降序队列(默认):priority_queue <int,vector< int >,less< int > >q; 相当于 priority_queue < int >
  2. 注意排名并列时是“1、2、3、3、5”而不是“1、2、3、3、4”

  3. sort自写的cmp函数中,参数类型若漏const会报奇奇怪怪的错误

  4. 若vector< int > vec(n + 1)且使用1-n而不使用vec[0],注意vec[0]的值对排序等后续算法造成的影响

    1. 排序时不应从begin开始而应从begin+1开始

目录

  1. B1015/A1062 德才论
  2. A1012 The Best Rank
  3. A1016 Phone Bills
  4. A1025 PAT Ranking
  5. A1028 List Sorting
  6. A1055 The World’s Richest
  7. A1075 PAT Judge
  8. A1083 List Grades
  9. A1080 Graduate Admission
  10. A1095 Cars on Campus

  1. B1015/A1062 德才论

    宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。”

    现给出一批考生的德才分数,请根据司马光的理论给出录取排名。

    输入格式:

    输入第一行给出 3 个正整数,分别为:N(≤105),即考生总数;L(≥60),为录取最低分数线,即德分和才分均不低于 L 的考生才有资格被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到但德分到线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于 H,但是德分不低于才分的考生属于“才德兼亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线 L 的考生也按总分排序,但排在第三类考生之后。

    随后 N 行,每行给出一位考生的信息,包括:准考证号 德分 才分,其中准考证号为 8 位整数,德才分为区间 [0, 100] 内的整数。数字间以空格分隔。

    输出格式:

    输出第一行首先给出达到最低分数线的考生人数 M,随后 M 行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。

    输入样例:
    14 60 80
    10000001 64 90
    10000002 90 60
    10000011 85 80
    10000003 85 80
    10000004 80 85
    10000005 82 77
    10000006 83 76
    10000007 90 78
    10000008 75 79
    10000009 59 90
    10000010 88 45
    10000012 80 100
    10000013 90 99
    10000014 66 60
    
    输出样例:
    12
    10000013 90 99
    10000012 80 100
    10000003 85 80
    10000011 85 80
    10000004 80 85
    10000007 90 78
    10000006 83 76
    10000005 82 77
    10000002 90 60
    10000014 66 60
    10000008 75 79
    10000001 64 90
    
    1. 我的

      #include <iostream>
      #include <vector>
      #include <algorithm>
      
      using namespace std;
      
      int low = 0, high = 0;
      
      typedef struct {
      	int id;
      	int de;
      	int cai;
      }Student;
      
      bool Cmp(const Student&a, const Student&b)
      {
      	int suma = a.de + a.cai, sumb = b.de + b.cai;
      	if (suma != sumb) return suma > sumb;
      	else if (a.de != b.de) return a.de > b.de; 
      	else return a.id < b.id;
      }
      
      void Output(vector<Student>&students)
      {
      	sort(students.begin(), students.end(), Cmp);
      	
      	for (int i = 0;i < students.size();++i) {
      		cout << students[i].id << " " << students[i].de << " " << students[i].cai << endl;
      	}
      }
      
      int main(void) 
      {
      	int n = 0;
      	cin >> n >> low >> high;
      	
      	vector<Student> students1, students2, students3, students4;
      	for (int i = 0;i < n;++i) {
      		int id = 0, de = 0, cai = 0;
      		cin >> id >> de >> cai;
      		
      		if (de >= low && cai >= low) {
      			Student student = {id, de, cai};
      			if (de >= high && cai >= high) students1.push_back({id, de, cai});
      			else if (de >= high && cai < high) students2.push_back({id, de, cai});
      			else if (de >= cai) students3.push_back({id, de, cai});
      			else students4.push_back({id, de, cai});
      		}
      	}
      	
      	cout << students1.size() + students2.size() + students3.size() + students4.size() << endl;
      	Output(students1);
      	Output(students2);
      	Output(students3);
      	Output(students4);
      	
      	return 0;
      }
      

      上面代码试了3次,两次通过,一次测试点3、4超时

      把上面重复部分写成函数调用试了,测试点3、4超时

    2. 《算法笔记》P96

      结构体里还存考生类别


  2. A1012 The Best Rank

    To evaluate the performance of our first year CS majored students, we consider their grades of three courses only: C - C Programming Language, M - Mathematics (Calculus or Linear Algrbra), and E - English. At the mean time, we encourage students by emphasizing on their best ranks – that is, among the four ranks with respect to the three courses and the average grade, we print the best rank for each student.

    For example, The grades of C, M, E and A - Average of 4 students are given as the following:

    StudentID  C  M  E  A
    310101     98 85 88 90
    310102     70 95 88 84
    310103     82 87 94 88
    310104     91 91 91 91
    

    Then the best ranks for all the students are No.1 since the 1st one has done the best in C Programming Language, while the 2nd one in Mathematics, the 3rd one in English, and the last one in average.

    Input Specification:

    Each input file contains one test case. Each case starts with a line containing 2 numbers N and M (≤2000), which are the total number of students, and the number of students who would check their ranks, respectively. Then N lines follow, each contains a student ID which is a string of 6 digits, followed by the three integer grades (in the range of [0, 100]) of that student in the order of C, M and E. Then there are M lines, each containing a student ID.

    Output Specification:

    For each of the M students, print in one line the best rank for him/her, and the symbol of the corresponding rank, separated by a space.

    The priorities of the ranking methods are ordered as A > C > M > E. Hence if there are two or more ways for a student to obtain the same best rank, output the one with the highest priority.

    If a student is not on the grading list, simply output N/A.

    Sample Input:
    5 6
    310101 98 85 88
    310102 70 95 88
    310103 82 87 94
    310104 91 91 91
    310105 85 90 90
    310101
    310102
    310103
    310104
    310105
    999999
    
    Sample Output:
    1 C
    1 M
    1 E
    1 A
    3 A
    N/A
    
    1. 我的

      #include <iostream>
      #include <vector>
      #include <map>
      #include <algorithm>
      
      using namespace std;
      
      const char COURSES[] = {'A', 'C', 'M', 'E'};
      
      int main(void)
      {
      	int n = 0, m = 0;
      	cin >> n >> m;
      	
      	map<int, vector<int>> grades;
      	vector<vector<int>> ranks(4, vector<int>(n, 0));
      	for (int i = 0;i < n;++i) {
      		int id = 0;
      		vector<int> courses(4, 0);
      		cin >> id >> courses[1] >> courses[2] >> courses[3];
      		courses[0] = (courses[1] + courses[2] + courses[3]) / 3;
      		grades[id] = courses;
      		
      		for (int j = 0;j < 4;++j) ranks[j].push_back(courses[j]);
      	}
      	for (int i = 0;i < 4;++i) sort(ranks[i].begin(), ranks[i].end(), greater<int>());
      	
      	for (int i = 0;i < m;++i) {
      		int id = 0;
      		cin >> id;
      		if (grades.end() == grades.find(id)) cout << "N/A" << endl;
      		else {
      			int rank = n;
      			char course = 0;
      			for (int j = 0;j < 4;++j) {
      				int pos = find(ranks[j].begin(), ranks[j].end(), grades[id][j]) - ranks[j].begin();
      				if (pos < rank) {
      					rank = pos;
      					course = COURSES[j];
      				}
      			}
      			cout << rank + 1 << " " << course << endl;
      		}
      	}
      	
      	return 0;
      }
      
    2. 《算法笔记》P99

      “……应该算作1、2、3、3、5。在具体实现时,切记不要算作1、2、3、3、4,否则中间3个测试点至少会错一个”

      本题没有明示平均分是否需要取整以及取整方式,根据题目描述中的例子可以看出是四舍五入。但本题采用向下取整的方式也能通过,或者采用更简洁的方式——不取平均,直接存储三门课的总分


  3. A1016 Phone Bills

    A long-distance telephone company charges its customers by the following rules

    Making a long-distance call costs a certain amount per minute, depending on the time of day when the call is made. When a customer starts connecting a long-distance call, the time will be recorded, and so will be the time when the customer hangs up the phone. Every calendar month, a bill is sent to the customer for each minute called (at a rate determined by the time of day). Your job is to prepare the bills for each month, given a set of phone call records.

    Input Specification:

    Each input file contains one test case. Each case has two parts: the rate structure, and the phone call records.

    The rate structure consists of a line with 24 non-negative integers denoting the toll (cents/minute) from 00:00 - 01:00, the toll from 01:00 - 02:00, and so on for each hour in the day.

    The next line contains a positive number N (≤1000), followed by N lines of records. Each phone call record consists of the name of the customer (string of up to 20 characters without space), the time and date (mm:dd:hh:mm), and the word on-line or off-line.

    For each test case, all dates will be within a single month. Each on-line record is paired with the chronologically next record for the same customer provided it is an off-line record. Any on-line records that are not paired with an off-line record are ignored, as are off-line records not paired with an on-line record. It is guaranteed that at least one call is well paired in the input. You may assume that no two records for the same customer have the same time. Times are recorded using a 24-hour clock.

    Output Specification:

    For each test case, you must print a phone bill for each customer.

    Bills must be printed in alphabetical order of customers’ names. For each customer, first print in a line the name of the customer and the month of the bill in the format shown by the sample. Then for each time period of a call, print in one line the beginning and ending time and date (dd:hh:mm), the lasting time (in minute) and the charge of the call. The calls must be listed in chronological order. Finally, print the total charge for the month in the format shown by the sample.

    Sample Input:
    10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
    10
    CYLL 01:01:06:01 on-line
    CYLL 01:28:16:05 off-line
    CYJJ 01:01:07:00 off-line
    CYLL 01:01:08:03 off-line
    CYJJ 01:01:05:59 on-line
    aaa 01:01:01:03 on-line
    aaa 01:02:00:01 on-line
    CYLL 01:28:15:41 on-line
    aaa 01:05:02:24 on-line
    aaa 01:04:23:59 off-line
    
    Sample Output:
    CYJJ 01
    01:05:59 01:07:00 61 $12.10
    Total amount: $12.10
    CYLL 01
    01:06:01 01:08:03 122 $24.40
    28:15:41 28:16:05 24 $3.85
    Total amount: $28.25
    aaa 01
    02:00:01 04:23:59 4318 $638.80
    Total amount: $638.80
    
    1. 我的

      #include <iostream>
      #include <vector>
      #include <map>
      #include <string>
      #include <algorithm>
      #include <iomanip>
      
      using namespace std;
      
      typedef struct {
      	string name;
      	string time;
      	string state;
      }Record;
      
      int rates[24] = {0};
      int total = 0;
      
      bool Cmp(const Record&a, const Record&b)
      {
      	if (a.name != b.name) return a.name < b.name;
      	else return a.time < b.time;
      }
      
      float Cal(const string&start, const string&end)
      {
      	int period = 0;
      	float bill = 0;
      	
      	int day1 = 0, hour1 = 0, minute1 = 0;
      	sscanf(start.c_str(),"%d:%d:%d", &day1, &hour1, &minute1);
      	int day2 = 0, hour2 = 0, minute2 = 0, second2 = 0;
      	sscanf(end.c_str(),"%d:%d:%d", &day2, &hour2, &minute2);
      	
      	for (int i = day1 + 1; i <= day2 - 1;++i) {
      		period += 24 * 60;
      		bill += total;
      	}
      	
      	if (day1 != day2) {
      		for (int i = hour1 + 1; i < 24;++i) {
      			period += 60;
      			bill += rates[i] * 60;
      		}
      		period += 60 - minute1;
      		bill += (float)rates[hour1] * (60 - minute1);
      		for (int i = 0; i < hour2;++i) {
      			period += 60;
      			bill += rates[i] * 60;
      		}
      		period += minute2;
      		bill += (float)rates[hour2] * minute2;
      	}
      	else {
      		for (int i = hour1 + 1; i < hour2;++i) {
      			period += 60;
      			bill += rates[i] * 60;
      		}
      		if (hour1 != hour2) {
      			period += 60 - minute1;
      			bill += (float)rates[hour1] * (60 - minute1);
      			period += minute2;
      			bill += (float)rates[hour2] * minute2;
      		}
      		else {
      			period += minute2 - minute1;
      			bill = (float)rates[hour1] * (minute2 - minute1);
      		}
      	}
      	
      	cout << period << " $" << setiosflags(ios::fixed) << setprecision(2) << bill / 100 << endl;
      	return bill;
      }
      
      int main(void)
      {
      	for (int i = 0; i < 24;++i) {
      		cin >> rates[i];
      		total += rates[i] * 60;
      	}
      	
      	int n = 0;
      	cin >> n;
      	
      	map<string, float> bills;
      	vector<Record> records;
      	for (int i = 0;i < n;++i) {
      		string name = "", time = "", state = "";
      		cin >> name >> time >> state;
      		records.push_back({name, time, state});
      	}
      	sort(records.begin(), records.end(), Cmp);
      	
      	string name = "";
      	float sum = 0;
      	for (int i = 0;i + 1 < n;++i) {
      		if (records[i].name == records[i + 1].name && records[i].state == "on-line" && records[i + 1].state == "off-line") {
      			if (records[i].name != name) {
      				if (name != "") cout << "Total amount: $" << setiosflags(ios::fixed) << setprecision(2) << sum / 100 << endl;;
      				name = records[i].name;
      				cout << name << " " << records[i].time[0] << records[i].time[1] << endl;
      				sum = 0;
      			}
      			string start = records[i].time.substr(3);
      			string end = records[i + 1].time.substr(3);
      			cout << start << " " << end << " ";
      			
      			sum += Cal(start, end);
      		}
      	}
      	if (name != "") cout << "Total amount: $" << setiosflags(ios::fixed) << setprecision(2) << sum / 100 << endl;;
      	
      	return 0;
      }
      

      泪如雨下,我把‘$’打成’&'找了半天错在哪

    2. 《算法笔记》P102

      1. “注意:资费的输出需要进行单位换算,即把cent换算为dollar,所以结果要除以100

      2. ”给出一组边界数据供读者测试:“

        10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
        5
        aaa 01:01:01:03 on-line
        aaa 01:02:00:01 on-line
        CYLL 01:28:15:41 on-line
        aaa 01:05:02:24 on-line
        aa 01:02:00:02 off-line
        
      3. “……对已知的起始时间和终止时间,只需要不断将起始时间加1,判断其是否到达终止时间即可

      temp = rec[on];
      while (temp.dd < rec[off].dd || temp.hh < rec[off].hh || temp.mm < rec[off].mm) {
      	time++;
      	money += toll[temp.hh];
      	temp.mm++;
      	if (temp.mm >= 60) {
      		temp.mm = 0;
      		temp.hh++;
      	}
      	if (temp.hh >= 24) {
      		temp.hh = 0;
      		temp.dd++;
      	}
      }
      

  4. A1025 PAT Ranking

    Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhejiang University. Each test is supposed to run simultaneously in several places, and the ranklists will be merged immediately after the test. Now it is your job to write a program to correctly merge all the ranklists and generate the final rank.

    Input Specification:

    Each input file contains one test case. For each case, the first line contains a positive number N (≤100), the number of test locations. Then N ranklists follow, each starts with a line containing a positive integer K (≤300), the number of testees, and then K lines containing the registration number (a 13-digit number) and the total score of each testee. All the numbers in a line are separated by a space.

    Output Specification:

    For each test case, first print in one line the total number of testees. Then print the final ranklist in the following format:

    registration_number final_rank location_number local_rank
    

    The locations are numbered from 1 to N. The output must be sorted in nondecreasing order of the final ranks. The testees with the same score must have the same rank, and the output must be sorted in nondecreasing order of their registration numbers.

    Sample Input:
    2
    5
    1234567890001 95
    1234567890005 100
    1234567890003 95
    1234567890002 77
    1234567890004 85
    4
    1234567890013 65
    1234567890011 25
    1234567890014 100
    1234567890012 85
    
    Sample Output:
    9
    1234567890005 1 1 1
    1234567890014 1 2 1
    1234567890001 3 1 2
    1234567890003 3 1 2
    1234567890004 5 1 4
    1234567890012 5 2 2
    1234567890002 7 1 5
    1234567890013 8 2 3
    1234567890011 9 2 4
    
    1. 我的

      #include <iostream>
      #include <vector>
      #include <algorithm>
      
      using namespace std;
      
      typedef struct {
      	long long id;
      	int score;
      	int localNumber;
      }Testee;
      
      bool Cmp(const Testee&a, const Testee&b)
      {
      	if (a.score != b.score) return a.score > b.score;
      	else return a.id < b.id;
      }
      
      int main(void)
      {
      	int n = 0, total = 0;
      	cin >> n;
      	vector<Testee> testees;
      	for (int i = 0;i < n;++i) {
      		int k = 0;
      		cin >> k;
      		total += k;
      		for (int j = 0;j < k;++j) {
      			long long id = 0;
      			int score = 0;
      			cin >> id >> score;
      			testees.push_back({id, score, i + 1});
      		}
      	}
      	sort(testees.begin(), testees.end(), Cmp);
      	
      	cout << total << endl;
      	int final = 1, local[301] = {0}, localScore[301] = {0}, localNow[301] = {0};
      	printf("%013lld", testees[0].id);
      	cout << " " << 1 << " " << testees[0].localNumber << " " << 1 << endl;
      	local[testees[0].localNumber] = 1;
      	localScore[testees[0].localNumber] = testees[0].score;
      	localNow[testees[0].localNumber] = 1;
      	for (int i = 1;i < total;++i) {
      		if (testees[i].score != testees[i - 1].score) final = i + 1;
      		if (testees[i].score != localScore[testees[i].localNumber]) {
      			local[testees[i].localNumber] = localNow[testees[i].localNumber] + 1;
      			localScore[testees[i].localNumber] = testees[i].score;
      		}
      		++localNow[testees[i].localNumber];
      		printf("%013lld", testees[i].id);
      		cout << " " << final << " " << testees[i].localNumber << " " << local[testees[i].localNumber] << endl;
      	}
       
      	return 0;
      }
      

      绝了:https://blog.csdn.net/qq_41325698/article/details/98032791

      测试点4会考id不够13位需要补0的情况,巨坑

    2. 《算法笔记》P109

      参考代码的结构体里存了local_rank,当读完一个考场的所有考生信息,就对该考场所有考生成绩进行排序(sort(stu + num - k, stu + num, cmp)),得到考场内排名


  5. A1028 List Sorting

    Excel can sort records according to any column. Now you are supposed to imitate this function.

    Input Specification:

    Each input file contains one test case. For each case, the first line contains two integers N (≤105) and C, where N is the number of records and C is the column that you are supposed to sort the records with. Then N lines follow, each contains a record of a student. A student’s record consists of his or her distinct ID (a 6-digit number), name (a string with no more than 8 characters without space), and grade (an integer between 0 and 100, inclusive).

    Output Specification:

    For each test case, output the sorting result in N lines. That is, if C = 1 then the records must be sorted in increasing order according to ID’s; if C = 2 then the records must be sorted in non-decreasing order according to names; and if C = 3 then the records must be sorted in non-decreasing order according to grades. If there are several students who have the same name or grade, they must be sorted according to their ID’s in increasing order.

    Sample Input 1:
    3 1
    000007 James 85
    000010 Amy 90
    000001 Zoe 60
    
    Sample Output 1:
    000001 Zoe 60
    000007 James 85
    000010 Amy 90
    
    Sample Input 2:
    4 2
    000007 James 85
    000010 Amy 90
    000001 Zoe 60
    000002 James 98
    
    Sample Output 2:
    000010 Amy 90
    000002 James 98
    000007 James 85
    000001 Zoe 60
    
    Sample Input 3:
    4 3
    000007 James 85
    000010 Amy 90
    000001 Zoe 60
    000002 James 90
    
    Sample Output 3:
    000001 Zoe 60
    000007 James 85
    000002 James 90
    000010 Amy 90
    
    1. 我的

      #include <iostream>
      #include <string>
      #include <vector>
      #include <algorithm>
      
      using namespace std;
      
      int c = 0;
      
      typedef struct {
      	int id;
      	string name;
      	int grade;
      }Record;
      
      bool Cmp(const Record&a, const Record&b)
      {
      	if (1 == c) return a.id < b.id;
      	else if (2 == c) {
      		if (a.name != b.name) return a.name < b.name;
      		else return a.id < b.id;
      	}
      	else {
      		if (a.grade != b.grade) return a.grade < b.grade;
      		else return a.id < b.id;
      	}
      }
      
      int main(void)
      {
      	int n = 0;
      	cin >> n >> c;
      	
      	vector<Record> records;
      	for (int i = 0;i < n;++i) {
      		int id = 0, grade = 0;
      		string name = "";
      		cin >> id >> name >> grade;
      		records.push_back({id, name, grade});
      	} 
      	sort(records.begin(), records.end(), Cmp);
      	
      	for (int i = 0;i < n;++i) {
      		printf("%06d", records[i].id);
      		cout << " " << records[i].name << " " << records[i].grade << endl;
      	}
       
      	return 0;
      }
      
      1. 《算法笔记》P112

  6. A1055 The World’s Richest

    Forbes magazine publishes every year its list of billionaires based on the annual ranking of the world’s wealthiest people. Now you are supposed to simulate this job, but concentrate only on the people in a certain range of ages. That is, given the net worths of N people, you must find the M richest people in a given range of their ages.

    Input Specification:

    Each input file contains one test case. For each case, the first line contains 2 positive integers: N (≤105) - the total number of people, and K (≤103) - the number of queries. Then N lines follow, each contains the name (string of no more than 8 characters without space), age (integer in (0, 200]), and the net worth (integer in [−106,106]) of a person. Finally there are K lines of queries, each contains three positive integers: M (≤100) - the maximum number of outputs, and [Amin, Amax] which are the range of ages. All the numbers in a line are separated by a space.

    Output Specification:

    For each query, first print in a line Case #X: where X is the query number starting from 1. Then output the M richest people with their ages in the range [Amin, Amax]. Each person’s information occupies a line, in the format

    Name Age Net_Worth
    

    The outputs must be in non-increasing order of the net worths. In case there are equal worths, it must be in non-decreasing order of the ages. If both worths and ages are the same, then the output must be in non-decreasing alphabetical order of the names. It is guaranteed that there is no two persons share all the same of the three pieces of information. In case no one is found, output None.

    Sample Input:
    12 4
    Zoe_Bill 35 2333
    Bob_Volk 24 5888
    Anny_Cin 95 999999
    Williams 30 -22
    Cindy 76 76000
    Alice 18 88888
    Joe_Mike 32 3222
    Michael 5 300000
    Rosemary 40 5888
    Dobby 24 5888
    Billy 24 5888
    Nobody 5 0
    4 15 45
    4 30 35
    4 5 95
    1 45 50
    
    Sample Output:
    Case #1:
    Alice 18 88888
    Billy 24 5888
    Bob_Volk 24 5888
    Dobby 24 5888
    Case #2:
    Joe_Mike 32 3222
    Zoe_Bill 35 2333
    Williams 30 -22
    Case #3:
    Anny_Cin 95 999999
    Michael 5 300000
    Alice 18 88888
    Cindy 76 76000
    Case #4:
    None
    
    1. 我的

      #include <iostream>
      #include <string>
      #include <vector>
      #include <algorithm>
      
      using namespace std;
      
      typedef struct {
      	string name;
      	int age;
      	int worth;
      }Info;
      
      bool Cmp(const Info&a, const Info&b)
      {
      	if (a.worth != b.worth) return a.worth > b.worth;
      	else if (a.age != b.age) return a.age < b.age;
      	else return a.name < b.name;
      }
      
      int main(void)
      {
      	int n = 0, k = 0;
      	cin >> n >> k;
      	
      	vector<Info> info;
      	for (int i = 0;i < n;++i) {
      		string name = "";
      		int age = 0, worth = 0;
      		cin >> name >> age >> worth;
      		info.push_back({name, age, worth});
      	}
      	sort(info.begin(), info.end(), Cmp);
      	
      	for (int i = 1;i <= k;++i) {
      		int m = 0, amin = 0, amax = 0;
      		cin >> m >> amin >> amax;
      		cout << "Case #" << i << ":" << endl;
      		
      		int count = 0;
      		for (int j = 0;j < n && count < m;++j) {
      			if (amin <= info[j].age && info[j].age <= amax) {
      				++count;
      				cout << info[j].name << " " << info[j].age << " " << info[j].worth << endl;
      			}
      		}
      		if (!count) cout << "None" << endl;
      	}
       
      	return 0;
      }
      

      测试点1可能运行超时,可以再点一次

      或者把cin, cout换成scanf, printf可能会好一点

    2. 《算法笔记》P115

      “步骤2:==注意到M的范围仅在100以内,因此可以进行预处理,即将每个年龄中财富在前100名以内的人全都存到另一个数组中(因为某个年龄中财富值在100名外的人永远不会被输出),后面查询的操作均在这个新数组中进行。==这个预处理操作将显著降低查询的复杂度,使得K次查询不会超时”

      “如果不进行步骤2的预处理,那么2号测试点会超时。如果在查询时单独对某个年龄区间内的人排序,也会超时”


  7. A1075 PAT Judge

    The ranklist of PAT is generated from the status list, which shows the scores of the submissions. This time you are supposed to generate the ranklist for PAT.

    Input Specification:

    Each input file contains one test case. For each case, the first line contains 3 positive integers, N (≤104), the total number of users, K (≤5), the total number of problems, and M (≤105), the total number of submissions. It is then assumed that the user id’s are 5-digit numbers from 00001 to N, and the problem id’s are from 1 to K. The next line contains K positive integers p[i] (i=1, …, K), where p[i] corresponds to the full mark of the i-th problem. Then M lines follow, each gives the information of a submission in the following format:

    user_id problem_id partial_score_obtained
    

    where partial_score_obtained is either −1 if the submission cannot even pass the compiler, or is an integer in the range [0, p[problem_id]]. All the numbers in a line are separated by a space.

    Output Specification:

    For each test case, you are supposed to output the ranklist in the following format:

    rank user_id total_score s[1] ... s[K]
    

    where rank is calculated according to the total_score, and all the users with the same total_score obtain the same rank; and s[i] is the partial score obtained for the i-th problem. If a user has never submitted a solution for a problem, then “-” must be printed at the corresponding position. If a user has submitted several solutions to solve one problem, then the highest score will be counted

    The ranklist must be printed in non-decreasing order of the ranks. For those who have the same rank, users must be sorted in nonincreasing order according to the number of perfectly solved problems. And if there is still a tie, then they must be printed in increasing order of their id’s. For those who has never submitted any solution that can pass the compiler, or has never submitted any solution, they must NOT be shown on the ranklist. It is guaranteed that at least one user can be shown on the ranklist.

    Sample Input:
    7 4 20
    20 25 25 30
    00002 2 12
    00007 4 17
    00005 1 19
    00007 2 25
    00005 1 20
    00002 2 2
    00005 1 15
    00001 1 18
    00004 3 25
    00002 2 25
    00005 3 22
    00006 4 -1
    00001 2 18
    00002 1 20
    00004 1 15
    00002 4 18
    00001 3 4
    00001 4 2
    00005 2 -1
    00004 2 0
    
    Sample Output:
    1 00002 63 20 25 - 18
    2 00005 42 20 0 22 -
    2 00007 42 - 25 - 17
    2 00001 42 18 18 4 2
    5 00004 40 15 0 25 -
    
    1. 我的

      #include <iostream>
      #include <vector>
      #include <algorithm>
      
      using namespace std;
      
      int k = 0;
      vector<int> fullMark(6, 0);
      
      bool Cmp(const vector<int>&a, const vector<int>&b)
      {
      	if (a[0] != b[0]) return a[0] > b[0];
      	else {
      		int count1 = 0, count2 = 0;
      		for (int i = 1;i <= k;++i) {
      			if (a[i] == fullMark[i]) ++count1;
      			if (b[i] == fullMark[i]) ++count2;
      		}
      		if (count1 != count2) return count1 > count2;
      		else return a[k + 1] < b[k + 1];
      	}
      }
      
      int main(void)
      {
      	int n = 0, m = 0;
      	cin >> n >> k >> m;
      	
      	for (int i = 1;i <= k;++i) cin >> fullMark[i];
      	
      	vector<vector<int>> submissions(n + 1, vector<int>(k + 2, -2));
      	for (int i = 0;i < m;++i) {
      		int id = 0, problem = 0, grade = 0;
      		cin >> id >> problem >> grade;
      		if (grade > submissions[id][problem]) submissions[id][problem] = grade;
      	}
      	
      	for (int i = 1;i <= n;++i) {
      		submissions[i][k + 1] = i;
      		for (int j = 1;j <= k;++j) {
      			if (submissions[i][j] >= 0) {
      				if (-2 == submissions[i][0]) submissions[i][0] = 0;
      				submissions[i][0] += submissions[i][j];
      			}
      			else if (-1 == submissions[i][j]) ++submissions[i][j];
      		}
      	}
      	sort(submissions.begin() + 1, submissions.end(), Cmp);
      	
      	int rank = 1, pre = submissions[1][0];
      	for (int i = 1;i <= n;++i) { 
      		if (submissions[i][0] >= 0) {
      			if (submissions[i][0] != pre) {
      				pre = submissions[i][0];
      				rank = i;
      			}
      			printf("%d %05d %d", rank, submissions[i][k + 1], submissions[i][0]);
      			for (int j = 1;j <= k;++j) {
      				if (-2 == submissions[i][j]) cout << " -";
      				else cout << " " << submissions[i][j];
      			}
      			cout << endl;
      		}
      	}
       
      	return 0;
      }
      

      注意排序要从begin + 1开始

    2. 《算法笔记》P118


  8. A1083 List Grades

    Given a list of N student records with name, ID and grade. You are supposed to sort the records with respect to the grade in non-increasing order, and output those student records of which the grades are in a given interval.

    Input Specification:

    Each input file contains one test case. Each case is given in the following format:

    N
    name[1] ID[1] grade[1]
    name[2] ID[2] grade[2]
    ... ...
    name[N] ID[N] grade[N]
    grade1 grade2
    

    where name[i] and ID[i] are strings of no more than 10 characters with no space, grade[i] is an integer in [0, 100], grade1 and grade2 are the boundaries of the grade’s interval. It is guaranteed that all the grades are distinct.

    Output Specification:

    For each test case you should output the student records of which the grades are in the given interval [grade1, grade2] and are in non-increasing order. Each student record occupies a line with the student’s name and ID, separated by one space. If there is no student’s grade in that interval, output NONE instead.

    Sample Input 1:
    4
    Tom CS000001 59
    Joe Math990112 89
    Mike CS991301 100
    Mary EE990830 95
    60 100
    
    Sample Output 1:
    Mike CS991301
    Mary EE990830
    Joe Math990112
    
    Sample Input 2:
    2
    Jean AA980920 60
    Ann CS01 80
    90 95
    
    Sample Output 2:
    NONE
    
    1. 我的

      #include <iostream>
      #include <string>
      #include <vector>
      #include <algorithm>
      
      using namespace std;
      
      typedef struct {
      	string name;
      	string id;
      	int grade;
      }Record;
      
      bool Cmp(const Record&a, const Record&b)
      {
      	return a.grade > b.grade;
      }
      
      int main(void)
      {
      	int n = 0;
      	cin >> n;
      	
      	vector<Record> records;
      	for (int i = 0;i < n;++i) {
      		string name = "", id = "";
      		int grade = 0;
      		cin >> name >> id >> grade;
      		records.push_back({name, id, grade});
      	}
      	sort(records.begin(), records.end(), Cmp);
      	
      	int grade1 = 0, grade2 = 0;
      	cin >> grade1 >> grade2;
       	int count = 0;
      	for (int i = 0;i < n;++i) {
       		if (grade1 <= records[i].grade && records[i].grade <= grade2) {
       			++count;
       			cout << records[i].name << " " << records[i].id << endl;
      		}
      	}
      	if (!count) cout << "NONE";
       
      	return 0;
      }
      
    2. 《算法笔记》P123


  9. A1080 Graduate Admission

    It is said that in 2011, there are about 100 graduate schools ready to proceed over 40,000 applications in Zhejiang Province. It would help a lot if you could write a program to automate the admission procedure.

    Each applicant will have to provide two grades: the national entrance exam grade GE, and the interview grade GI. The final grade of an applicant is (GE+GI)/2. The admission rules are:

    • The applicants are ranked according to their final grades, and will be admitted one by one from the top of the rank list.
    • If there is a tied final grade, the applicants will be ranked according to their national entrance exam grade GE. If still tied, their ranks must be the same.
    • Each applicant may have K choices and the admission will be done according to his/her choices: if according to the rank list, it is one’s turn to be admitted; and if the quota of one’s most preferred shcool is not exceeded, then one will be admitted to this school, or one’s other choices will be considered one by one in order. If one gets rejected by all of preferred schools, then this unfortunate applicant will be rejected.
    • If there is a tied rank, and if the corresponding applicants are applying to the same school, then that school must admit all the applicants with the same rank, even if its quota will be exceeded.
    Input Specification:

    Each input file contains one test case.

    Each case starts with a line containing three positive integers: N (≤40,000), the total number of applicants; M (≤100), the total number of graduate schools; and K (≤5), the number of choices an applicant may have.

    In the next line, separated by a space, there are M positive integers. The i-th integer is the quota of the iii-th graduate school respectively.

    Then N lines follow, each contains 2+K integers separated by a space. The first 2 integers are the applicant’s GE and GI, respectively. The next KKK integers represent the preferred schools. For the sake of simplicity, we assume that the schools are numbered from 0 to M−1, and the applicants are numbered from 0 to N−1.

    Output Specification:

    For each test case you should output the admission results for all the graduate schools. The results of each school must occupy a line, which contains the applicants’ numbers that school admits. The numbers must be in increasing order and be separated by a space. There must be no extra space at the end of each line. If no applicant is admitted by a school, you must output an empty line correspondingly.

    Sample Input:
    11 6 3
    2 1 2 2 2 3
    100 100 0 1 2
    60 60 2 3 5
    100 90 0 3 4
    90 100 1 2 0
    90 90 5 1 3
    80 90 1 0 2
    80 80 0 1 2
    80 80 0 1 2
    80 70 1 3 2
    70 80 1 2 3
    100 100 0 2 4
    
    Sample Output:
    0 10
    3
    5 6 7
    2 8
    
    1 4
    
    1. 我的

      #include <iostream>
      #include <vector>
      #include <algorithm>
      #include <queue>
      
      using namespace std;
      
      typedef struct {
      	int id;
      	int sum;
      	int ge;
      	vector<int> choices;
      	int school;
      }Info;
      
      bool Cmp(const Info&a, const Info&b)
      {
      	if (a.sum != b.sum) return a.sum > b.sum;
      	else return a.ge > b.ge;
      }
      
      int main(void)
      {
      	int n = 0, m = 0, k = 0;
      	cin >> n >> m >> k;
      	
      	vector<int> quota(m, 0);
      	for (int i = 0;i < m;++i) cin >> quota[i];
      	
      	vector<Info> info;
      	for (int i = 0;i < n;++i) {
      		int ge = 0, gi = 0;
      		cin >> ge >> gi;
      		vector<int> choices(k, 0);
      		for (int j = 0;j < k;++j) cin >> choices[j];
      		info.push_back({i, ge + gi, ge, choices});
      	}
      	sort(info.begin(), info.end(), Cmp);
      	
      	vector<int> lastid(m, -1);
      	vector<priority_queue<int, vector<int>, greater<int>>> admissions(m);
       	for (int i = 0;i < n;++i) {
      		for (int j = 0;j < k;++j) {
      			int school = info[i].choices[j];
      			if (quota[school]) {
      				--quota[school];
      				lastid[school] = i;
      				admissions[school].push(info[i].id);
      				break;
      			}
      			else if (lastid[school] != -1 && info[i].sum == info[lastid[school]].sum && info[i].ge == info[lastid[school]].ge) {
                      admissions[school].push(info[i].id);
      				break;
      			}
      		}
      	}
      	
      	for (int i = 0;i < m;++i) {
      		for (int j = 0;!admissions[i].empty();admissions[i].pop(), ++j) j ? (cout << " " << admissions[i].top()) : (cout << admissions[i].top());
      		cout << endl;
      	}
       
      	return 0;
      }
      

      因为vector info写成vector info(n),最后一个测试点老是段错误,找bug找到失去理智

      知道应该是数组越界,但找了其它所有我觉得可能越界的地方,愣是没看到这一行,orz

    2. 《算法笔记》P126

      “……下面这组数据,输出应为5个空行“

      5 5 3
      0 0 0 5 5
      100 100 0 1 2
      100 99 1 2 0
      99 100 2 1 0
      99 99 1 0 2
      98 98 2 0 1
      

  10. A1095 Cars on Campus

    1. 我的

      #include <iostream>
      #include <string>
      #include <vector>
      #include <algorithm>
      #include <map>
      
      using namespace std;
      
      typedef struct {
          string id;
          string time;
          string state;
      }Record;
      
      bool Cmp1(const Record&a, const Record&b)
      {
          if (a.id != b.id) return a.id < b.id;
          else return a.time < b.time;
      }
      bool Cmp2(const Record&a, const Record&b)
      {
          if (a.state.size() == 1 && b.state.size() > 1) return true;
          else if (a.state.size() > 1 && b.state.size() == 1) return false;
          else return a.time < b.time;
      }
      
      int main(void)
      {
          int n = 0, k = 0;
          cin >> n >> k;
      
          vector<Record> records;
          for (int i = 0;i < n;++i) {
              string id = "", time = "", state = "";
              cin >> id >> time >> state;
              records.push_back({id, time, state});
          }
          sort(records.begin(), records.end(), Cmp1);
      
          int count = 0;
          map<string, int> periods;
          for (int i = 0;i + 1 < n;++i) {
              if (records[i].id == records[i + 1].id && records[i].state == "in" && records[i + 1].state == "out") {
                  records[i].state = "i";
                  records[i + 1].state = "o";
                  count += 2;
      
                  int h1 = 0, m1 = 0, s1 = 0;
                  sscanf(records[i].time.c_str(), "%d:%d:%d", &h1, &m1, &s1);
                  int start = h1*3600+m1*60+s1;
                  int h2 = 0, m2 = 0, s2 = 0;
                  sscanf(records[i + 1].time.c_str(), "%d:%d:%d", &h2, &m2, &s2);
                  int end = h2*3600+m2*60+s2;
                  periods[records[i].id] += end - start;
              }
          }
          sort(records.begin(), records.end(), Cmp2);
      
          vector<int> cars(24*3600, 0);
          int h1 = 0, m1 = 0, s1 = 0;
          sscanf(records[0].time.c_str(), "%d:%d:%d", &h1, &m1, &s1);
          int start = h1*3600+m1*60+s1;
          int car = 1;
          for (int i = 1;i < count;++i) {
              int h2 = 0, m2 = 0, s2 = 0;
              sscanf(records[i].time.c_str(), "%d:%d:%d", &h2, &m2, &s2);
              int end = h2*3600+m2*60+s2;
              for (int j = start;j < end;++j) cars[j] = car;
      
              records[i].state == "i" ? ++car : --car;
              start = end;
          }
      
          for (int i = 0;i < k;++i) {
              string time = "";
              cin >> time;
              int h1 = 0, m1 = 0, s1 = 0;
              sscanf(time.c_str(), "%d:%d:%d", &h1, &m1, &s1);
              cout << cars[h1*3600+m1*60+s1] << endl;
          }
      
          map<string, int>::iterator iter = periods.begin();
          vector<string> ids;
          ids.push_back(iter->first);
          for(++iter;iter != periods.end();++iter) {
              if (iter->second > periods[ids[0]]) {
                  ids.clear();
                  ids.push_back(iter->first);
              }
              else if (iter->second == periods[ids[0]]) ids.push_back(iter->first);
          }
          for (int i = 0;i < (int)ids.size();++i) cout << ids[i] << " ";
          int period = periods[ids[0]];
          printf("%02d:%02d:%02d", period / 3600, (period % 3600) / 60, period % 60);
      
          return 0;
      }
      

      这题印象很深,半年前第一次做的时候超时了,后来看牛客网的题解茅塞顿开。这次再做就比较顺了

    2. 《算法笔记》P132

      “……由于查询的时刻是按照时间顺序递增的,因此可以设置一个变量now,用以指向valid数组里面的记录,使得now指向的记录的时刻不超过本次欲查询的时刻;同时设置一个变量numCar,以记录当前校园内的车辆数。显然,当valid[now]为"in"时,numCar加1;而当valid[now]是“out”时,numCar减1”


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值