【OpenJudge3344】冷血格斗场

原题:(见http://noi.openjudge.cn/ch0309/3344/
描述

为了迎接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

题目大意:给你一个初始只有一个元素的序列和一些插入操作,要求对于每一个插入操作,都找到两个实力值最接近的元素i,j(如果有其他元素和i的实力值相等,则选择他们id中最小的一个)
方法:用set或者map动态维护这个序列,每当加入一个元素时利用lower_bound()和upper_bound()找出当前序列中和i实力最接近的元素j。并且判断当前序列中是否存在i(或存在但id比较大),如果是就将i插入序列中。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#define maxn 100005
#define inf 100000010;
using namespace std;
int n;
map<int,int>mp;//建立从实力值到id号的映射mp
map<int,int>::iterator it;
int main()
{
    //freopen("my.in","r",stdin);
    //freopen("my.out","w",stdout);

    mp[1000000000]=1;//facer的实力和id
    scanf("%d",&n);//n条信息
    for(int i=1;i<=n;i++)
    {
        int id,d;
        scanf("%d%d",&id,&d);   

        it=mp.lower_bound(d);//在映射中查找和新会员实力值最接近的;
        if(it==mp.end())it--;//找不到就是序列中最后一个元素和d最接近(因为map会自动根据下标排序)

        int t=abs(d-it->first),idx;
        idx=it->second;//得到最接近的人的实力值和id
        if(it!=mp.begin())
        {
            it--;
            if(t>abs(it->first - d) || (t==abs(it->first - d) && it->second<idx))//因为可能这个人之前出现过,所以这里还要判断t>abs(it->first - d)
            idx=it->second;
        }
        printf("%d %d\n",id,idx);

        it=mp.find(d);//查找新加入的人是否已经存在
        if(it==mp.end()//不存在 || it->second > id//存在但这次id比较小)
        {
            mp[d]=id;
        }

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值