热血格斗场和冷血格斗场

好的吧,过去很久的题目了,现在补一发。跟格斗场有仇。每个都提交了十几次。
先摘一下题目。

5:热血格斗场
描述
为了迎接08年的奥运会,让大家更加了解各种格斗运动,facer新开了一家热血格斗场。格斗场实行会员制,但是新来的会员不需要交入会费,而只要同一名老会员打一场表演赛,证明自己的实力。
我们假设格斗的实力可以用一个正整数表示,成为实力值。另外,每个人都有一个唯一的id,也是一个正整数。为了使得比赛更好看,每一个新队员都会选择与他实力最为接近的人比赛,即比赛双方的实力值之差的绝对值越小越好,如果有两个人的实力值与他差别相同,则他会选择比他弱的那个(显然,虐人必被虐好)。
不幸的是,Facer一不小心把比赛记录弄丢了,但是他还保留着会员的注册记录。现在请你帮facer恢复比赛纪录,按照时间顺序依次输出每场比赛双方的id。
输入
第一行一个数n(0 < n <=100000),表示格斗场新来的会员数(不包括facer)。以后n行每一行两个数,按照入会的时间给出会员的id和实力值。一开始,facer就算是会员,id为1,实力值1000000000。输入保证两人的实力值不同。
输出
N行,每行两个数,为每场比赛双方的id,新手的id写在前面。
样例输入
3
2 1
3 3
4 2
样例输出
2 1
3 2
4 2

一开始我是仿照郭神的学生信息录入和查询系统那样写的,也就是每次循环一遍map找实力和它最接近的。然后发现理解错了题目,ID和入会时间无关,样例数据太有迷惑性了。这样就需要每次输入都进行处理。其次就是,这样时间会超。因此,我们不能采用又一重循环,而需要用STL中的lower_bound和upper_bound进行处理。
但是还是写挂了,也许晚上脑子不太清醒。
注意点是,如果返回的lower_bound是begin,那么说明没有比这个会员更菜的,它自己就是begin,那么不需要比较直接输出upper_bound,这其实是个很弱智的结论但是我当时傻了……可能两种思路一下没转换过来。
然后我之前还加了个while……emmm不知道自己当时在干啥。
最后AC代码:

#include <iostream>
#include <map>
#include <cmath>
#include <algorithm>
#include <stdio.h>
using namespace std;
class member {
public:
	int force;
	struct info {
		int order;
		int id;
	};
	info data;
};
typedef map<int, int> MAP;
int main() {
	MAP record;
	member A;
	int n;
	scanf("%d", &n);
	A.data.id = 1;
	A.data.order = 0;
	A.force = 1000000000;
	record.insert(MAP::value_type(A.force, A.data.id));
	for (int i = 1; i <= n; i++) {
		A.data.order = i;
		scanf("%d%d", &A.data.id, &A.force);
		record.insert(MAP::value_type(A.force, A.data.id));
		int mindis = 1000000000;
		typename MAP::iterator pp1 = record.lower_bound(A.force);
		typename MAP::iterator pp2 = record.upper_bound(A.force);
		if (pp1 == record.begin()){
			printf("%d %d\n", A.data.id, pp2->second);
			continue;
		}
		--pp1;
		printf("%d %d\n", A.data.id, (abs(A.force - pp1->first) > abs(A.force - pp2->first) ? pp2->second : pp1->second));
	}
	return 0;
}

冷血格斗场似乎更难一些,我参考了别人的代码才AC。
先上题目:

3:冷血格斗场
总时间限制: 1000ms 内存限制: 65536kB
描述
为了迎接08年的奥运会,让大家更加了解各种格斗运动,facer新开了一家冷血格斗场。格斗场实行会员制,但是新来的会员不需要交入会费,而只要同一名老会员打一场表演赛,证明自己的实力。
我们假设格斗的实力可以用一个正整数表示,成为实力值,两人的实力值可以相同。另外,每个人都有一个唯一的id,也是一个正整数。为了使得比赛更好看,每一个新队员都会选择与他实力最为接近的人比赛,即比赛双方的实力值之差的绝对值越小越好,如果有多个人的实力值与他差别相同,则他会选择id最小的那个。
不幸的是,Facer一不小心把比赛记录弄丢了,但是他还保留着会员的注册记录。现在请你帮facer恢复比赛纪录,按照时间顺序依次输出每场比赛双方的id。
输入
第一行一个数n(0 < n <=100000),表示格斗场新来的会员数(不包括facer)。以后n行每一行两个数,按照入会的时间给出会员的id和实力值。一开始,facer就算是会员,id为1,实力值1000000000。
输出
N行,每行两个数,为每场比赛双方的id,新手的id写在前面。
样例输入
3
2 3
3 1
4 2
样例输出
2 1
3 2
4 2

先上AC代码:

# include <iostream>
# include <map>
using namespace std;
typedef map <int, int> MYMAP;
struct member {
	int force;
	int id;
};
int main () {
	int n;
	cin >> n;
	member A;
	MYMAP record;
	record.insert (MYMAP::value_type (1000000000, 1));
	for (int i = 0; i < n; i++) {
		scanf ("%d%d", &A.id, &A.force);
		typename MYMAP::iterator p1 = record.lower_bound (A.force);
		typename MYMAP::iterator p2 = record.upper_bound (A.force);
		MYMAP::iterator low = record.lower_bound (A.force);
		MYMAP::iterator up = record.upper_bound (A.force);
		if (low == record.end()) {
			--low;
			printf ("%d %d\n", A.id, low->second);
		}
		else if (low == record.begin()) {
			printf ("%d %d\n", A.id, low->second);
		}
		else if (low->first == A.force){
			printf ("%d %d\n", A.id, low->second);
		}
		else {
			--low;
			if (A.force - low->first < up->first - A.force) {
				printf ("%d %d\n", A.id, low->second);
			}
			else if (A.force - low->first > up->first - A.force) {
				printf ("%d %d\n", A.id, up->second);
			}
			else {
				printf ("%d %d\n", A.id, (low->second < up->second? low->second: up->second));
			}
		}
		if (record.find(A.force) != record.end()) {
			record[A.force] = min(A.id, record[A.force]);
		}
		else record.insert (MYMAP::value_type (A.force, A.id));
	}
	return 0;
}

第一遍的时候我傻傻地保留了所有的信息然后遍历找到ID最小的那个,然后挂了(其实感觉思路除了冗长一点之外没什么问题但是就是没过)
第二遍的时候我在AC代码的基础上,把insert分散在了每个if-else那里,把最后的if-else删了,然后挂了。
好吧其实并不知道为什么,从逻辑上看也没有什么问题……一篇不太合格的题解,放在这里提醒自己代码要简洁,简洁,简洁好了。

猜你喜欢

转载自blog.csdn.net/weixin_44288817/article/details/89840811