题目链接:

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. vue.js插件使用(02) vue-router

    概述 vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用.vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来.传统的 ...

  2. 输出内容(document.write)四种写法

    第一种:输出内容用""括起,直接输出""号内的内容 <script type="text/javascript"> docume ...

  3. jquery ajax跨域请求详解

    本文章来给大家详细jquery中的ajax跨域请求, 在JQuery对于Ajax的跨域请求有两类解决方案,不过都是只支持get方式.分别是JQuery的jquery.ajax jsonp格式和jque ...

  4. 旋转转盘选择Menu--第三方开源--CircleMenu

    CircleMenu在github上的项目主页是:https://github.com/zhangphil/Android-CircleMenu CircleMenu用法简单,JAVA代码: pack ...

  5. WinSock编程基础

    一.套接字模式   1.阻塞模式       创建套接字时,默认是阻塞模式,对recv函数调用会使程序进入等待状态,知道接收到数据才返回.   2.非阻塞模式:      可以调用ioctlsocke ...

  6. 傅里叶变换 fft_generic halcon

    傅立叶变换(FT, Fourier Transform)的作用是将一个信号由时域变换到频域.其实就是把数据由横坐标时间.纵坐标采样值的波形图格式,转换为横坐标频率.纵坐标振幅(或相位)的频谱格式.变换 ...

  7. yhd日志分析(二)

    yhd日志分析(二) 继续yhd日志分析,统计数据 日期 uv pv 登录人数 游客人数 平均访问时长 二跳率 独立ip数 1 分析 登录人数 count(distinct endUserId) 游客 ...

  8. Simplified Memory Modle C/C++内存模型

    最近学习c++看视频时,老师时常提到栈区堆区,搞不清楚,只能泪目,毕竟爱过...因此,接下来对此做些整理,方便回顾.(老师说:这个简化模型仅用于初学者示意,与实际模型并不完全一致) 1.stack(栈 ...

  9. 第四节:监视AppDomain

    宿主应用程序可监视AppDomain消耗的资源.有的宿主根据这种信息判断一个AppDomain的内存或CPU消耗是否超过了应有的水准,并强制卸载一个AppDomain. 还可以利用监视来比较不同算法的 ...

  10. C 几种异常机制简单讲述

    引言 这是关于C中如何使用异常机制的讨论.顺带讲一讲C中魔法函数的setjmp内部机制.通过它实现高级的异常try...catch. 允许我先扯一段面试题. 对于计算机面试题. 算法题等.觉得还是有意 ...