题意:
进入少林寺,在闯关成功后需要找一个已经进入少林寺的僧人进行一场比武。
规则如下:
根据新人的武力值,新人会找一个与他武力值最相近的僧人进行比武。如果有两个符合条件的,他会选择武力值比他小的僧人进行比武。
现在把进入少林寺的人的顺序给你,让你把比武的双方的id输出。
*每个人的武力值以及id都是唯一的。
思路:
线段树
题目中已经把新人入门的顺序给你。只要询问一下新人的左边最大武力值是谁,新人的右边最小武力值是谁即可。
询问完后把新人插入到线段树中即可。
复杂度O(nlogn)。
我这里根据武力值大小离散化了一下。
code:
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
const int MAXN = 1e5+5;
const int INF = 0x3f3f3f3f;
const int MINF = -1;
#define start 1, n+1, 1
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
int n;
map <int, int> mp;
struct ST
{
int minv, maxv;
}st[MAXN<<2];
struct Monk
{
int id, gra;
int rank;
int id2; //record the grade level;
}mk[MAXN];
bool cmp(const Monk &a, const Monk &b)
{
return a.gra < b.gra;
}
bool cmp2(const Monk &a, const Monk &b)
{
return a.rank < b.rank;
}
void lishanhua()
{
int id = 1;
for(int i = 0;i < n+1; i++)
mk[i].id2 = id++;
}
void update(int l, int r, int rt, int pp, int val)
{
if(l == r)
{
st[rt].minv = min(st[rt].minv, val);
st[rt].maxv = max(st[rt].maxv, val);
return ;
}
int mid = (l+r)/2;
if(pp <= mid) update(lson, pp, val);
else update(rson, pp, val);
st[rt].minv = min(st[rt<<1].minv, st[rt<<1|1].minv);
st[rt].maxv = max(st[rt<<1].maxv, st[rt<<1|1].maxv);
}
int querymin(int l, int r, int rt, int x, int y)
{
if(x <= l && y >= r)
{
return st[rt].minv;
}
int mid = (l+r)/2;
int tt = INF;
if(x <= mid) tt = min(tt, querymin(lson, x, y));
if(y > mid) tt = min(tt, querymin(rson, x, y));
return tt;
}
int querymax(int l, int r, int rt, int x, int y)
{
if(x <= l && y >= r)
{
return st[rt].maxv;
}
int mid = (l+r)/2;
int tt = -1;
if(x <= mid) tt = max(tt, querymax(lson, x, y));
if(y > mid) tt = max(tt, querymax(rson, x, y));
return tt;
}
int main()
{
while(scanf("%d", &n) != EOF)
{
if(n == 0) break;
mk[0] = (Monk){1, 1e9, 0};
for(int i = 1;i <= n; i++)
{
scanf("%d%d", &mk[i].id, &mk[i].gra);
mk[i].rank = i;
}
//init seg tree
for(int i = 1;i <= (n<<2); i++)
{
st[i].minv = INF, st[i].maxv = -1;
}
sort(mk, mk+n+1, cmp);
lishanhua();
sort(mk, mk+n+1, cmp2);
mp.clear();
for(int i = 0;i < n+1; i++)
{
mp[mk[i].gra] = mk[i].id;
}
update(start, mk[0].id2, mk[0].gra);
for(int i = 1;i <= n; i++)
{
const int tt = mk[i].id2;
int minv = INF, maxv = -1;
minv = min(minv, querymin(start, tt, n+1));
maxv = max(maxv, querymax(start, 1, tt));
//cout<<"minv = "<<minv<<" maxv = "<<maxv<<endl;
if(maxv == -1)
printf("%d %d\n", mk[i].id, mp[minv]);
else
{
int t1 = abs(minv- mk[i].gra), t2 = abs(maxv - mk[i].gra);
if(t2 <= t1)
printf("%d %d\n", mk[i].id, mp[maxv]);
else
printf("%d %d\n", mk[i].id, mp[minv]);
}
update(start, mk[i].id2, mk[i].gra);
}
}
return 0;
}
/*
5
2 1
3 3
4 2
5 100
6 80
*/