1055 The World's Richest (25分)走向优秀之路

今天写的第一个题,题目描述看起来并不男,这个也确实很容易想,一开始直接用结构体存储数据,然后每次创建新的结构体数组保存每次查询的人进行 自定义cmp结构体排序,很容易实现,第一次跑出了唯一一个超时没有出来,其他还是可以的。
代码如下:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
struct Person {
	string name;
	int age;
	int worth;
};
bool cmp(Person&A, Person&B) {
	return A.worth == B.worth ? (A.age == B.age ? (A.name<B.name) : A.age < B.age) : A.worth >B.worth;
}
int main() {
	int N, M, age1, num, age2;
	scanf("%d %d", &N, &M);
	vector<Person>V;
	Person tmp;
	for (int i = 0; i < N; i++) {
		cin.ignore();
		cin >> tmp.name >> tmp.age >> tmp.worth;
		V.push_back(tmp);
	}
	for (int i = 0; i < M; i++) {
		scanf("%d %d %d", &num, &age1, &age2);
		vector<Person>V2;
		for (int i = 0; i < V.size(); i++) {
			if (V[i].age >= age1 && V[i].age <= age2)V2.push_back(V[i]);
		}
		sort(V2.begin(), V2.end(), cmp);
		printf("Case #%d:\n", i + 1);
		if (V2.size() == 0) {
			printf("None\n"); continue;
		}
		for (int j = 0; j < min(num, (int)V2.size()); j++) printf("%s %d %d\n", V2[j].name.c_str(), V2[j].age, V2[j].worth);
	}
	return 0;
}

在这里插入图片描述
但是很显然有一个超时,有一个差点超时,肯定不能就这么放了他。
于是我想到,是不是每次库函数sort排序太费时间了?
很自然我想到了把库函数删掉,改用直接存取的堆进行处理,于是出现了set版本的二次代码,不过这里我遇到了一个小问题,因为我是在原函数的基础上修改的,所以下图出现了一个问题
在这里插入图片描述如果要查询的数量num大于Set的数量还好说,不会出错,问题是如果S的数量太,因为S不能像数组一样访问下标,所以每次只能这样取元素,导致每次循环j都会改变循环条件,解决方法就是在外面用一个变量直接取第一次set的大小,就可以修正了。
二次代码如下:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
struct Person {
	string name;
	int age;
	int worth;
};
bool operator<(const Person&A, const Person&B) {
	return A.worth == B.worth ? (A.age == B.age ? (A.name<B.name) : A.age < B.age) : A.worth >B.worth;
}
int main() {
	int N, M, age1, num, age2;
	scanf("%d %d", &N, &M);
	vector<Person>V;
	Person tmp;
	for (int i = 0; i < N; i++) {
		cin.ignore();
		cin >> tmp.name;
		scanf("%d %d", &tmp.age, &tmp.worth);
		V.push_back(tmp);
	}
	for (int i = 0; i < M; i++) {
		scanf("%d %d %d", &num, &age1, &age2);
		set<Person>S;
		for (int i = 0; i < V.size(); i++) {
			if (V[i].age >= age1 && V[i].age <= age2)
				S.insert(V[i]);
		}
		printf("Case #%d:\n", i + 1);
		if (S.size() == 0) {
			printf("None\n"); continue;
		}
		int m = S.size();
		for (int j = 0; j <min(num, m); j++) { 
			printf("%s %d %d\n", S.begin()->name.c_str(), S.begin()->age, S.begin()->worth);
			S.erase(S.begin());
		}
	}
	return 0;
}

在这里插入图片描述很显然优秀了一丢丢,因为第1个测试点已经减少了50ms处理时间,但是对第二个还是没法救回来。
于是乎,把仅存的一个cin>>string改成char数组,可是我一开始忘记了修改cmp里面的函数,导致出错了几个测试的,我一度怀疑自己是不是用错了c预言的string,终于吃了个饭回来一眼就看到了这个错误。

经过修改:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<string.h>
using namespace std;
struct Person {
	char name[10];
	int age;
	int worth;
};
bool operator<(const Person&A, const Person&B) {
	return A.worth == B.worth ? (A.age == B.age ? (strcmp(A.name,B.name)<0?true:false) : A.age < B.age) : A.worth >B.worth;
}
int main() {
	int N, M, age1, num, age2;
	scanf("%d %d", &N, &M);
	vector<Person>V;
	Person tmp;
	for (int i = 0; i < N; i++) {
		cin.ignore();
		scanf("%s", tmp.name);
		scanf("%d %d", &tmp.age, &tmp.worth);
		V.push_back(tmp);
	}
	for (int i = 0; i < M; i++) {
		scanf("%d %d %d", &num, &age1, &age2);
		set<Person>S;
		for (int i = 0; i < V.size(); i++) {
			if (V[i].age >= age1 && V[i].age <= age2)
				S.insert(V[i]);
		}
		printf("Case #%d:\n", i + 1);
		if (S.size() == 0) {
			printf("None\n"); continue;
		}
		int m = S.size();
		for (int j = 0; j <min(num, m); j++) {
			printf("%s %d %d\n",S.begin()->name,S.begin()->age, S.begin()->worth);
			S.erase(S.begin());
		}
	}
	return 0;
}

在这里插入图片描述好吧,还是需要对输入进行处理了,不能每次都线型找表。

经过简单修改,还是超时!

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<string.h>
using namespace std;
struct Person {
	char name[10];
	int age;
	int worth;
};
bool operator<(const Person&A, const Person&B) {
	return A.worth == B.worth ? (A.age == B.age ? (strcmp(A.name,B.name)<0?true:false) : A.age < B.age) : A.worth >B.worth;
}
int main() {
	int N, M, age1, num, age2;
	scanf("%d %d", &N, &M);
	vector<vector<Person> >V(201);
	Person tmp;
	for (int i = 0; i < N; i++) {
		cin.ignore();
		scanf("%s", tmp.name);
		scanf("%d %d", &tmp.age, &tmp.worth);
		V[tmp.age].push_back(tmp);
	}
	for (int i = 0; i < M; i++) {
		scanf("%d %d %d", &num, &age1, &age2);
		set<Person>S;
		for (int i = age1; i <=age2; i++) {
			for (int j = 0; j < V[i].size(); j++)S.insert(V[i][j]);
		}
		printf("Case #%d:\n", i + 1);
		if (S.size() == 0) {
			printf("None\n"); continue;
		}
		int m = S.size();
		for (int j = 0; j <min(num, m); j++) {
			printf("%s %d %d\n",S.begin()->name,S.begin()->age, S.begin()->worth);
			S.erase(S.begin());
		}
	}
	return 0;
}

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200107120943135.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ppWXVUb25nWHVl,size_16,color_FFFFFF,t_70额,可是我已经把第1个优化到40ms的水平了,还是应付不了第2个,再次优化!

经过我仔细分析,很显然查询语句最多103次,而人的数据最多105次,我猜他肯定是直接取年龄范围0-200,这样就导致每次都是108数量级以上的次数,肯定会超时。

参考了晴神的书,这个题写了蛮久的,当然拿大半分还是很简单的,但是做人嘛,不追求完美那多没意思。

AC代码:

#include<iostream>
#include<vector>
#include<algorithm>
#include<string.h>
using namespace std;
struct Person {
	char name[10];
	int age, worth;
};
bool cmp(Person&A, Person&B) {
	return A.worth == B.worth ? (A.age == B.age ? (strcmp(A.name, B.name) < 0 ? true : false) : (A.age < B.age)) : A.worth > B.worth;
}
vector<Person>V(100010);
vector<Person>Y(100010);
int P[201] = { 0 };
int main() {
	int N, M, age1, age2, num, ym = 0;
	scanf("%d %d", &N, &M);
	for (int i = 0; i < N; i++) {
		scanf("%s %d %d", &V[i].name, &V[i].age, &V[i].worth);
	}
	sort(V.begin(), V.begin()+N, cmp);
	for (int i = 0; i < N; i++) {
		if (P[V[i].age] < 100) {
			P[V[i].age]++;
			Y[ym++] = V[i];
		}
	}
	for (int j = 0; j < M; j++) {
		scanf("%d %d %d", &num, &age1, &age2);
		int printm = 0;
		printf("Case #%d:\n", j + 1);
		for (int i = 0; i < ym&&printm < num; i++) {
			if (Y[i].age >= age1 && Y[i].age <= age2) {
				printf("%s %d %d\n", Y[i].name, Y[i].age, Y[i].worth);
				printm++;
			}
		}
		if (printm==0)printf("None\n");
	}
	return 0;
}

通过这个题我还是学到了很多东西,首先:
大容量的数组最好写在函数外面,因为写在函数里的变量能申请的空间很小,写在外面可以很大。
第二个就是,要进行预处理,就是减少循环里面的运算,而是尽量写到循环外面,不然一个103次方的循环里,随便一点运算复杂度都会增加三个数量级复杂度。但是写到循环外面就可以做到和循环并列复杂度,n+n远小于nn
还有一个地方就是注意分清楚每个变量的意思,不然一个地方写的不合适,也许会骗过很多测试点,但是总有那种大数据的测试点过不了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值