Codeforces Round #353 (Div. 2) D. Tree Construction 二叉搜索树
题目链接:
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 二叉搜索树的更多相关文章
- Codeforces Round #353 (Div. 2) D. Tree Construction 模拟
D. Tree Construction 题目连接: http://www.codeforces.com/contest/675/problem/D Description During the pr ...
- 数据结构 - Codeforces Round #353 (Div. 2) D. Tree Construction
Tree Construction Problem's Link ------------------------------------------------------------------- ...
- Codeforces Round #353 (Div. 2) D. Tree Construction (二分,stl_set)
题目链接:http://codeforces.com/problemset/problem/675/D 给你一个如题的二叉树,让你求出每个节点的父节点是多少. 用set来存储每个数,遍历到a[i]的时 ...
- Codeforces Round #499 (Div. 1) F. Tree
Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...
- [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 ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- [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 ...
- [LeetCode] Binary Search Tree Iterator 二叉搜索树迭代器
Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the ro ...
- [LeetCode] Recover Binary Search Tree 复原二叉搜索树
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
随机推荐
- c#使用DocX添加多级标题
博客转移到 http://jacean.github.io/ 继续分享编程经验 先上效果.可以生成多级标题,但是不能生成1,1.1,1.2这样的自动序列, 只是这样的效果. 实现方法是给Paragra ...
- MongoDB查询语法
mongoDb是非关系型数据库,用习惯了mssql,mysql等数据库的需要转换一下思维 mongoDb存的是与js的json结构一样的文档,表中的每一条记录都可以结构不同 1,大于,小于,大于等于, ...
- linux下关于mysqldump备份的.sql导入数据库表数据丢失优化
直切正题 前2个随笔做了linux下自动备份,但是备份的.sql文件发现表数据丢失,原因是数据库太大我的数据库文件是804M,在用ftp拉去也会丢失数据 所以对db.sh备份数据库加一个压缩gizp ...
- Pull解析xml
没有写抛出的异常,例子是含有多个Person对象persons.xml(此片内容未写写入的代码),包含id,name,email,address标签,Person对象含有id,name,email,a ...
- delphi 基础之四 delphi 组织结构
delphi 组织结构 在Delphi中,一个正在开发的应用程序可以被称作项目或者工程.一般地,一个项目主要由dpr(项目).pas(单元)和dfm(窗体)三种文件组成,另外还有一些附属文件,如res ...
- Java 装箱 拆箱
Java 自动装箱与拆箱 ??什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能. 一般我们要创建一个类的对象的时候,我 ...
- USB总线介绍
•USB 1.0出现在1996年的,速度只有1.5Mb/s1998年升级为USB 1.1,速度也提升到12Mb/s,称之为”full speed” •USB2.0规范是由USB1.1规范演变而来的.它 ...
- angularjs2 学习笔记(一) 开发环境搭建
开发环境,vs2013 update 5,win7 x64,目前最新angular2版本为beta 17 第一步:安装node.js 安装node.js(https://nodejs.org/en/) ...
- [原创]PostgreSQL Plus Advanced Server监控工具PEM(四)
四.PEM管理工具 1.编辑配置 选择进行管理的目标服务器,点击菜单Tools->Server Configuration->postgresql.conf管理服务器配置,可以看到我们经常 ...
- core java 10~12(多线程 & I/O & Network网络编程)
MODULE 10 Threads 多线程-------------------------------- 进程: 计算机在运行过程中的任务单元,CPU在一个时间点上只能执行一个进程,但在一个时间段上 ...