OPENJUDGE 冷血格斗场

//upper_bound Returns the first elment beyond the range

# include <iostream>
# include <cstdio>
# include <map>
# include <cmath>

using namespace std;

multimap<int,int> member;

int findMin(multimap<int,int>::iterator& start, multimap<int,int>::iterator& end) //找到区间中最小id
{
	multimap<int,int>::iterator i;
	int min = 1000000001;
	for ( i = start; i != end; i++ )
	{
		if ( i->second < min )
		{
			min = i->second;
		}
	}
	return min;
}

int findMinEXPT(multimap<int,int>::iterator& start, multimap<int,int>::iterator& end, int id)	//找到除本身外的最小id
{
	multimap<int,int>::iterator i;
	int min = 1000000001;
	for ( i = start; i != end; i++ )
	{
		if ( i->second < min && i->second != id )
		{
			min = i->second;
		}
	}
	return min;
}

multimap<int,int>::iterator findPos(int p,int id)
{
	multimap<int,int>::iterator i;
	for ( i = member.lower_bound(p); i != member.upper_bound(p); i++ )
	{
		if ( i->second == id )
		{
			return i;
		}
		
	}
	return member.end();
}



void match(int p,int id)
{
	int matchID = 0;
	int matchID_sub = 0;
	int lower = 0;
	int upper = 0;
	multimap<int,int>::iterator i;
	multimap<int,int>::iterator j;
	multimap<int,int>::iterator k;
	j = member.lower_bound(p);
	k = member.upper_bound(p);
	k--;
	if ( j != member.end() && k != member.end() )
	{

		if ( j == k )	//There is only one element that has the power p
		{
			if ( j == member.begin() )	//插入元素是第一个,则只需寻找其后满足条件的答案
			{
				i = j;
				k++;
				j++;
				k = member.upper_bound(k->first);
				matchID = findMin(j,k);
				printf("%d %d\n",i->second,matchID);
			}
			else	//插入元素不是第一个,则需要两头寻找
			{
				i = j;
				j--;
				k++;
				lower = i->first - j->first;
				upper = k->first - i->first;
				if ( lower < upper )	//如果左邻实力更接近,则寻找左邻中id最小的
				{
					j = member.lower_bound(j->first);
					matchID = findMin(j,i);
					printf("%d %d\n",i->second,matchID);

				}
				else if ( lower > upper )
				{
					j++;
					j++;
					k = member.upper_bound(k->first);
					matchID = findMin(j,k);
					printf("%d %d\n",i->second,matchID);
				}
				else	//如果两遍实力相差一样,那么就在两个区间的并集中寻找id最小的
				{
					int currentID = i->second;
					int downRange = j->first;
					int upRange = k->first;
					j = member.lower_bound(downRange);
					k = member.upper_bound(upRange);
					matchID = findMin(j,i);
					j = i;
					j++;
					matchID_sub = findMin(j,k);
					int finalMatch = min(matchID,matchID_sub);
					printf("%d %d\n",currentID,finalMatch);
					
				}
			}
		}
		else	//如果有多个选手实力与新手相等,那么在这些人中找id最小的即可
		{
			k++;
			i = findPos(p,id);
			matchID = findMinEXPT(j,k,i->second);
			printf("%d %d\n",i->second,matchID);
		}
	}
	else return;
}

int main()
{
	int n = 0;
	int id = 0;
	int power = 0;
	cin >> n;
	member.insert(make_pair(1000000000,1));
	for ( int i = 0; i < n; i++ )
	{
		scanf("%d%d",&id,&power);
		member.insert(make_pair(power,id));
		match(power,id);
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值