Codeforces Round #353 (Div. 2) D. Tree Construction (BST询问父亲节点)

原题请戳这里

题意:

给出n个不同的数,按照给出的顺序构造二叉排序树BST,第1个数为根节点。输出2-n个

节点的父亲节点。

分析:

二叉排序树的平均复杂度是log2n,最坏情况下变成线性的,复杂度为n。

对n个节点的插入操作如果用结构体指针的写法最坏情况下为n2=1010,这样会超时。

开始没有注意这点,TLE。但是正好复习了BST的插入操作递归和非递归的写法。

易知,插入的数的父亲节点是已插入的比它大或者比它小的与其最接近的数之一。

这个题利用set保存输入的数,用两个map分别记录左右孩子。

每次找到第一个大于v的数的位置。如果是最后一个,则前一个比它小的数的右孩子是该数;

否则,若找到的位置的左孩子为空,则该数为其左孩子,若不为空,则该数为前一个位置比

它小的数的右孩子。

这样复杂度是nlogn(循环n,lower_bound二分原理复杂度为logn)

#include<cstdio>
#include<map>
#include<algorithm>
#include<iostream>
#include<set>

using namespace std;

typedef long long ll;

set<int> numbers;
map<int,int> L,R;

int main()
{
    int n,v;
    while(~scanf("%d",&n))
    {
        numbers.clear();
        L.clear();
        R.clear();
        for(int i=0;i<n;i++)
        {
            scanf("%d",&v);
            if(i==0) numbers.insert(v);
            else
            {
                set<int>::iterator iter;
                iter = numbers.lower_bound(v);
                if(iter == numbers.end()) R[*(--iter)] = v;
                else
                {
                    if(!L[*iter]) L[*iter] = v;
                    else R[*(--iter)] = v;
                }
                if(i==1) printf("%d",*iter);
                else printf(" %d",*iter);
                numbers.insert(v);
            }
        }
        printf("\n");
    }
    return 0;
}

超时的BST插入非递归写法

#include<cstdio>
#include<map>
#include<algorithm>
#include<iostream>

using namespace std;

typedef long long ll;

struct node
{
    int val;
    struct node *lchild,*rchild,*fa;
};
int x[100005];
struct node *rt;
map<int,int> mp;

void insert_(int x,struct node*cur)
{
    struct node* ch = (struct node*)malloc(sizeof(struct node));
    ch->val = x;
    ch->lchild = ch->rchild = NULL;
    struct node* parent;
    while(cur!=NULL)
    {
        parent = cur;
        if(x > parent->val) cur = parent->rchild;
        else cur = parent->lchild;
    }
    ch->fa = parent;
    mp[x] = parent->val;
    if(parent->val < x)
        parent->rchild = ch;
    else
        parent->lchild = ch;
}

int main()
{
    int n,root;
    while(~scanf("%d",&n))
    {
        mp.clear();
        rt = (struct node*)malloc(sizeof(struct node));
        scanf("%d",&root);
        rt->val = root;
        rt->lchild = rt->rchild = NULL;
        for(int i=1;i<n;i++)
        {
            scanf("%d",&x[i]);
            insert_(x[i],rt);
        }
        for(int i=1;i<n-1;i++)
            printf("%d ",mp[x[i]]);
        printf("%d\n",mp[x[n-1]]);
    }
    return 0;
}
时间: 2024-08-06 11:30:12

Codeforces Round #353 (Div. 2) D. Tree Construction (BST询问父亲节点)的相关文章

数据结构 - Codeforces Round #353 (Div. 2) D. Tree Construction

Tree Construction Problem's Link ---------------------------------------------------------------------------- Mean: 给定n个数,按照构造Binary Search Tree的方式来构造BST树,按顺序输出每一个非root结点的父节点的值. analyse: 构造BST树最坏情况下时间复杂度为O(n),肯定会超时. 注意到只需要输出结点的父节点的值,不需要真的构造BST树. 插到第i

Codeforces Round #353 (Div. 2) D. Tree Construction (二分,stl_set)

题目链接:http://codeforces.com/problemset/problem/675/D 给你一个如题的二叉树,让你求出每个节点的父节点是多少. 用set来存储每个数,遍历到a[i]的时候查找比a[i]大的数的位置,然后插入,而父亲就是刚好比a[i]小的数或刚好大的数. 然后讨论是哪一个数. 比如给你3 1 2 ,如图 1的父亲是3 ,2的父亲是1. 那我其实只要找左边或右边出现最晚的数就行了,用pair的first表示a[i],second表示出现的顺序i. 1 #include

Codeforces Round #353 (Div. 2) ABCDE 题解 python

Problems # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring Painting standard input/output 1 s, 256 MB    x2519 C Money Transfers standard input/output 1 s, 256 MB    x724 D Tree Construction standard input/output 2

[Codeforces] Round #353 (Div. 2)

A题题意:给出一个等差数列的首项和公差,求x是否是该数列中的项 1 #include<bits/stdc++.h> 2 using namespace std; 3 int main(){ 4 int a,b,c; 5 scanf("%d%d%d",&a,&b,&c); 6 if(c>0&&b-a>=0&&(b-a)%c==0)printf("YES\n"); 7 else if(c&l

Codeforces Round #540 (Div. 3) F1. Tree Cutting (Easy Version) 【DFS】

任意门:http://codeforces.com/contest/1118/problem/F1 F1. Tree Cutting (Easy Version) time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given an undirected tree of nn vertices. Some vert

Codeforces Round #629 (Div. 3) E. Tree Queries(lca题)

https://codeforces.com/contest/1328/problem/E E. Tree Queries You are given a rooted tree consisting of nn vertices numbered from 11 to nn. The root of the tree is a vertex number 11. A tree is a connected undirected graph with n−1n−1 edges. You are

Codeforces Round #316 (Div. 2) D. Tree Requests 树 离线在线 算法

D. Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Roman planted a tree consisting of n vertices. Each vertex contains a lowercase English letter. Vertex 1 is the root of the

Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)

https://codeforces.com/contest/1328/problem/E 题目所描述的是一棵树,题中已明示1为root结点. 题目可以转化为,是否存在一条路径,满足集合中的k个点到路径的距离小于等于1? 思路: 1.首先倍增离线预处理出结点深度,便于后续在线询问LCA 2.对于每次的询问,依次扫描k个点.对于集合中的u和v两点,每次我们求出u和v的LCA,计算u和v到LCA的距离,如果u和v到LCA的距离同时大于1,那么说明无法找到一条路径,使得u和v到该路径链的距离小于等于1

Codeforces Round #316 (Div. 2) D Tree Requests

官方题解是离线询问,dfs树形转线性,然后二分找区间. 还有一种比较好的做法是直接dfs,将当前访问这个结点u相关的询问之前的状态存起来,然后访问完以后利用异或开关性,得到这颗子树上的答案. 代码是学习别人的http://blog.csdn.net/squee_spoon/article/details/47666667 当时做的时候想得是树形转线性,觉得dfs会暴栈,想用bfs,之前又没写过,于是愣了一个钟头. #include<bits/stdc++.h> using namespace