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

能正青
2023-12-01

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       : AnICoo1
Created Time : 2016-08-23-20.48 Tuesday
File Name    : D:\MyCode\2016-8月\2016-8-23-2.cpp
LANGUAGE     : 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-8
using 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;
//head

int 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;
}
 类似资料: