题目链接:

http://codeforces.com/contest/675/problem/D

题意:

给你一系列点,叫你构造二叉搜索树,并且按输入顺序输出除根节点以外的所有节点的父亲。

题解:

n有10^5,如果直接去建树,最会情况会O(n^2)t掉。

因此我们需要利用一些二叉搜索树的性质:

对于当前输入节点v,找出已经输入的最大的l和最小的r使得l<v<r。

由于输入v之前l和r中间是没有数的,所以l和r必定为祖先和后代的关系,如果不是的话,就会导致l和r中间还有数(l和r的公共祖先)

那么由于v必然会是l的右儿子或者r的左儿子,但现在这两个位置是不可能同时为空的(l和r的祖先和后代关系导致的),所以,真正能插入的地方就只有一个。

具体实现看代码。

 #include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
using namespace std; set<int> numbers;
map<int, int> lef, rig; int n;
void init() {
numbers.clear();
lef.clear(); rig.clear();
} int main() {
int v;
while (scanf("%d", &n) == && n) {
init();
scanf("%d", &v);
numbers.insert(v);
vector<int> ans;
for (int i = ; i < n - ; i++) {
scanf("%d", &v);
set<int>::iterator it = numbers.upper_bound(v);
if (it != numbers.end() && lef[*it]==) {
ans.push_back(*it);
lef[*it] = ;
}
else {
it--;
ans.push_back(*it);
rig[*it] = ;
}
numbers.insert(v);
}
for (int i = ; i < ans.size()-; i++) printf("%d ", ans[i]);
printf("%d\n", ans[ans.size() - ]);
}
return ;
}

贴一个avl模板代替set操作:

 #include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
using namespace std; const int INF = 1e9+; //AVL树节点信息
class TreeNode
{
public:
TreeNode() :lson(NULL), rson(NULL), freq(), hgt() {}
int data;//值
int hgt;//高度
unsigned int freq;//频率
TreeNode* lson;//指向左儿子的地址
TreeNode* rson;//指向右儿子的地址
};
//AVL树类的属性和方法声明
class AVLTree
{
private:
TreeNode* root;//根节点
void insertpri(TreeNode* &node,int x,int &pre,int &aft);//插入
int height(TreeNode* node);//求树的高度
void SingRotateLeft(TreeNode* &k2);//左左情况下的旋转
void SingRotateRight(TreeNode* &k2);//右右情况下的旋转
void DoubleRotateLR(TreeNode* &k3);//左右情况下的旋转
void DoubleRotateRL(TreeNode* &k3);//右左情况下的旋转
int Max(int cmpa, int cmpb);//求最大值
public:
AVLTree() :root(NULL) {}
void insert(int x,int &pre,int &aft);//插入接口
};
//计算节点的高度
int AVLTree::height(TreeNode* node)
{
if (node != NULL)
return node->hgt;
return -;
}
//求最大值
int AVLTree::Max(int cmpa, int cmpb)
{
return cmpa>cmpb ? cmpa : cmpb;
}
//左左情况下的旋转
void AVLTree::SingRotateLeft(TreeNode* &k2)
{
TreeNode* k1;
k1 = k2->lson;
k2->lson = k1->rson;
k1->rson = k2; k2->hgt = Max(height(k2->lson), height(k2->rson)) + ;
k1->hgt = Max(height(k1->lson), k2->hgt) + ;
k2 = k1;
}
//右右情况下的旋转
void AVLTree::SingRotateRight(TreeNode* &k2)
{
TreeNode* k1;
k1 = k2->rson;
k2->rson = k1->lson;
k1->lson = k2; k2->hgt = Max(height(k2->lson), height(k2->rson)) + ;
k1->hgt = Max(height(k1->rson), k2->hgt) + ;
k2 = k1;
}
//左右情况的旋转
void AVLTree::DoubleRotateLR(TreeNode* &k3)
{
SingRotateRight(k3->lson);
SingRotateLeft(k3);
}
//右左情况的旋转
void AVLTree::DoubleRotateRL(TreeNode* &k3)
{
SingRotateLeft(k3->rson);
SingRotateRight(k3);
}
//插入
void AVLTree::insertpri(TreeNode* &node, int x,int &pre,int &aft)
{
if (node == NULL)//如果节点为空,就在此节点处加入x信息
{
node = new TreeNode();
node->data = x;
return;
}
if (node->data>x)//如果x小于节点的值,就继续在节点的左子树中插入x
{
aft = node->data;
insertpri(node->lson, x,pre,aft);
if ( == height(node->lson) - height(node->rson))
if (x<node->lson->data)
SingRotateLeft(node);
else
DoubleRotateLR(node);
}
else if (node->data<x)//如果x大于节点的值,就继续在节点的右子树中插入x
{
pre = node->data;
insertpri(node->rson, x,pre,aft);
if ( == height(node->rson) - height(node->lson))//如果高度之差为2的话就失去了平衡,需要旋转
if (x>node->rson->data)
SingRotateRight(node);
else
DoubleRotateRL(node);
}
else ++(node->freq);//如果相等,就把频率加1
node->hgt = Max(height(node->lson), height(node->rson)) + ;
}
//插入接口
void AVLTree::insert(int x,int &pre,int &aft)
{
insertpri(root, x,pre,aft);
} map<int, int> lef, rig; int n;
void init() {
lef.clear(); rig.clear();
} int main() {
int v,pre,aft;
while (scanf("%d", &n) == && n) {
AVLTree tree;
init();
scanf("%d", &v);
tree.insert(v, pre, aft);
vector<int> ans;
for (int i = ; i < n - ; i++) {
scanf("%d", &v);
pre = , aft = INF;
tree.insert(v, pre, aft);
//printf("pre:%d,aft:%d\n", pre, aft);
if (aft!=INF && lef[aft] == ) {
ans.push_back(aft);
lef[aft] = ;
}
else {
ans.push_back(pre);
rig[pre] = ;
}
}
for (int i = ; i < ans.size() - ; i++) printf("%d ", ans[i]);
printf("%d\n", ans[ans.size() - ]);
}
return ;
}

Codeforces Round #353 (Div. 2) D. Tree Construction 二叉搜索树的更多相关文章

  1. Codeforces Round #353 (Div. 2) D. Tree Construction 模拟

    D. Tree Construction 题目连接: http://www.codeforces.com/contest/675/problem/D Description During the pr ...

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

    Tree Construction Problem's Link ------------------------------------------------------------------- ...

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

    题目链接:http://codeforces.com/problemset/problem/675/D 给你一个如题的二叉树,让你求出每个节点的父节点是多少. 用set来存储每个数,遍历到a[i]的时 ...

  4. Codeforces Round #499 (Div. 1) F. Tree

    Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...

  5. [CareerCup] 4.5 Validate Binary Search Tree 验证二叉搜索树

    4.5 Implement a function to check if a binary tree is a binary search tree. LeetCode上的原题,请参见我之前的博客Va ...

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

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  7. [LeetCode] Verify Preorder Sequence in Binary Search Tree 验证二叉搜索树的先序序列

    Given an array of numbers, verify whether it is the correct preorder traversal sequence of a binary ...

  8. [LeetCode] Binary Search Tree Iterator 二叉搜索树迭代器

    Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the ro ...

  9. [LeetCode] Recover Binary Search Tree 复原二叉搜索树

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

随机推荐

  1. objective-C常量与变量

    1.Objective-C中声明常量使用关键字const.如:const double PI = 3.1514; 2.Objective-C中变量可以分为成员变量.局部变量和全局变量(用的很少,尽量不 ...

  2. Dynamic view

    Views are a useful feature of SQL databases, letting us create virtual tables based on SQL select st ...

  3. ASP.NET中application对象

    ASP.NET中application对象的使用. Application对象的应用  1.使用Application对象保存信息  (1).使用Application对象保存信息  Applicat ...

  4. js对象与this指向

    创建对象的方法 1.对象字面量法 var obj={} var obj={ 'first-name':'Tom', 'last-name':'bush', age:24, Family:{ Broth ...

  5. linux内核SPI总线驱动分析(二)(转)

    简而言之,SPI驱动的编写分为: 1.spi_device就构建并注册  在板文件中添加spi_board_info,并在板文件的init函数中调用spi_register_board_info(s3 ...

  6. 17.python自定义函数

    什么是函数,函数说白了就是将一系列代码封装起来,实现代码的重用. 什么是代码重用? 假设我有这样的需求: 但是我还是觉得太麻烦了,每次想吃饭的时候都要重复这样的步骤.此时,我希望有这样的机器:

  7. 【转】IT领域技能图谱

  8. Python 以正确的宽度在盒子中居中打印一个字符

    注意://为整除的意思 代码: # -*- coding:UTF-8 -*- sentence = input("Sentence:") screen_width = 80 tex ...

  9. SequoiaDB版本升级及导入导出工具说明

    升级SequoiaDB数据库指导 SequoiaDB安装路径:SDB_HOME=/opt/sequoiadb 数据存储路径:DATABASE=/ opt/sequoiadb/database 一.导出 ...

  10. Git 设置别名[alias]

    工作中我经常设置一下别名... 别名就在[alias]后面,要删除别名,直接把对应的行删掉即可. 而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中: $ cat .git ...