http://codeforces.com/contest/675/problem/D
题意给你一个序列,按给出的顺序,构造二叉搜索树
求最后的树里每个节点的父亲
直接set模拟,显然对于任何一个点,插入之后,其父亲必然是按大小排序后的左边或右边的元素(端点的情况特判)
所以直接在set找到左边右边的元素,然后判断 左边的右儿子是否可用,或右边的左儿子,哪边可用插哪边咯。
nlogn
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
int ans[100005];
map<int ,int >mp;
int rr[100005],ll[100005];
set<int>:: iterator it,ed;
set<int> sb;
int main( )
{
int n;
int i,x;
cin>>n;
for (i=1;i<=n;i++)
{
scanf("%d",&x);
mp[x]=i;
sb.insert(x);
if (i==1) continue;
it=sb.lower_bound(x);
ed=sb.end();ed--;
if (it==sb.begin())
{
ans[i]=*(++it);
ll[mp[*it]]=x;
}
else if (it==ed)
{
ans[i]=*(--it);
rr[mp[*it]]=x;
}
else
{
int val_left=*(--it);
int id_left=mp[val_left];
it++;
int val_right=*(++it);
int id_right=mp[val_right];
if (rr[id_left])
{
ans[i]=val_right;
ll[id_right]=x;
}
else
{
ans[i]=val_left;
rr[id_left]=x;
}
}
}
for (i=2;i<=n;i++)
{
if (i>2)printf(" ");
printf("%d",ans[i]);
}
printf("\n");
return 0;
}