Codeforces Round #353 (Div. 2) D. Tree Construction (二叉搜索树+set)

来源:互联网 发布:jre 6u37 windows x64 编辑:程序博客网 时间:2024/06/08 19:15

D. Tree Construction

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

During the programming classes Vasya was assigned a difficult problem. However, he doesn’t know how to code and was unable to find the solution in the Internet, so he asks you to help.

You are given a sequence a, consisting of n distinct integers, that is used to construct the binary search tree. Below is the formal description of the construction process.

First element a1 becomes the root of the tree.Elements a2, a3, ..., an are added one by one. To add element ai one needs to traverse the tree starting from the root and using the following rules:    The pointer to the current node is set to the root.    If ai is greater than the value in the current node, then its right child becomes the current node. Otherwise, the left child of the current node becomes the new current node.    If at some point there is no required child, the new node is created, it is assigned value ai and becomes the corresponding child of the current node. 

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 100 000) — the length of the sequence a.

The second line contains n distinct integers ai (1 ≤ ai ≤ 109) — the sequence a itself.
Output

Output n - 1 integers. For all i > 1 print the value written in the node that is the parent of the node with value ai in it.
Examples
Input

3
1 2 3

Output

1 2

Input

5
4 2 3 1 6

Output

4 2 2 4

题意:将一个序列按照顺序插入到一棵二叉搜索树中,求除了根节点外的结点的父亲结点的值。

思路:如果按照普通的二叉搜索树进行插入,那么肯定是不行的,时间复杂度会到达O(n2),所以说要进行优化,我们知道二叉搜索树用到了排序,因为set本身也是可以自动排序的,所以说我们用一个set来存这棵树,每次插入num时寻找set中第一个大于num的数,就可以知道num需要插入的位置,那么一般来说,它的父节点就是那个比它大的数,但是会有特殊情况,如果比它大的数存在左儿子,那么num的父节点就是那个左儿子,例如数据:9913,5174,8700,9783,1364,1060,3026,8836,1634,6005,6200,这个序列形成图中,6200插入的时候,第一个大于它的数为8700,但是画图可得6200的父节点是6005,即8700的左儿子,具体可画图。所以我们用一个map来标记结点是否存在左儿子,如果存在,那么父节点为那个左儿子,否则为那个结点。

ac代码:

/* ***********************************************Author       : AnICoo1Created Time : 2016-08-23-20.48 TuesdayFile Name    : D:\MyCode\2016-8月\2016-8-23-2.cppLANGUAGE     : C++Copyright  2016 clh All Rights Reserved************************************************ */#include<stdio.h>#include<math.h>#include<string.h>#include<stack>#include<set>#include<map>#include<queue>#include<vector>#include<iostream>#include<algorithm>#define LL long long#define ll __int64#define mem(x,y) memset(x,(y),sizeof(x))#define PI acos(-1)#define gn (sqrt(5.0)+1)/2#define eps 1e-8using namespace std;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}ll lcm(ll a,ll b){return a/gcd(a,b)*b;}ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}double dpow(double a,ll b){double ans=1.0;while(b){if(b%2)ans=ans*a;a=a*a;b/=2;}return ans;}const ll INF=1e9+10;const int MAXN=1e6+10;const int MOD=1e9+7;//headint a[MAXN],fa[MAXN];set<int>s;set<int>::iterator it,iit;//遍历迭代器map<int,int>mp;//标记int main(){    int n;cin>>n;    for(int i=1;i<=n;i++) cin>>a[i];    for(int i=1;i<=n;i++) fa[i]=i;    s.clear();s.insert(a[1]);mp.clear();    for(int i=2;i<=n;i++)    {        it=s.lower_bound(a[i]);//二分查找,返回一个指针        if(it==s.end())//如果插入的数最大,s.end()为NULL,需要向前推        {            iit=--s.end();            fa[i]=*iit;        }        else if(it==s.begin())//如果插入数最小        {            fa[i]=*it;            mp[*it]++;//标记结点有了左儿子        }        else        {            if(mp[*it])//检查是否有左儿子                fa[i]=*--it;            else                fa[i]=*it,mp[*it]++;        }        s.insert(a[i]);    }    for(int i=2;i<=n;i++)        printf("%d ",fa[i]);    return 0;}
0 0