1. 程式人生 > 實用技巧 >[PAT] A1055 The World's Richest

[PAT] A1055 The World's Richest

排序(需優化)

題目大意

給出n個人的姓名、年齡和擁有的錢,然後進行k次查詢,每次查詢輸出在年齡區間內的財富值的從大到小的前m個人的資訊。如果財富值相同就就先輸出年齡小的,如果年齡相同就把名字按照字典序排序輸出。

思路

不能先排序然後根據每一個條件再新建一個數組、對新陣列排序的方法,這樣測試點2會超時。(排序是非常耗時的,所以排序用得越少越好,儘量只排一次,然後用空間換時間)
而可以注意到,n和m的值懸殊,n有10的5次方,m卻只有100個。所以先把所有的人按照財富值排序,再建立一個數組book標記每個年齡段擁有的人的數量,遍歷陣列並統計相應年齡的人數,當前年齡的人的數量不超過100的時候壓入新的陣列,多出來的不要壓入新陣列中(也就是說只取每個年齡的前100名),再從這個新的數組裡面取符合相應年齡的人的資訊。這樣就把排序轉化為了查詢。

AC程式碼

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAX 100002
struct node {
	char name[10];
	int age, worth;
};
vector<node>people, temp, ans;
int book[MAX] = { 0 };
bool cmp(node a, node b) {
	if (a.worth != b.worth)return a.worth > b.worth;
	else if (a.age != b.age)return a.age < b.age;
	else return strcmp(a.name, b.name) < 0;
}
int main() {
	int n, k, m, amin, amax;
	scanf("%d %d", &n, &k);
	people.resize(n);
	for (int i = 0; i < n; i++)
		scanf("%s %d %d", people[i].name, &people[i].age, &people[i].worth);
	sort(people.begin(), people.end(), cmp);
	for (int i = 0; i < n; i++) {
		if (book[people[i].age] < 100) {
			book[people[i].age]++;
			temp.push_back(people[i]);
		}
	}
	for (int i = 0; i < k; i++) {
		ans.clear();
		scanf("%d %d %d", &m, &amin, &amax);
		if (i != 0)printf("\n");
		printf("Case #%d:", i + 1);
		for (int j = 0; j < temp.size(); j++) {
			if (temp[j].age >= amin && temp[j].age <= amax && ans.size() < m) {
				ans.push_back(temp[j]);
			}
		}
		if (ans.size() == 0)printf("\nNone");
		for (int j = 0; j < ans.size(); j++) {
			printf("\n%s %d %d", ans[j].name, ans[j].age, ans[j].worth);
		}
	}
	return 0;
}