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 ...
随机推荐
- DataGridView控件判断滚动条是否滚动到当前已加载的数据行底部
private void dgvLoad_Scroll(object sender, ScrollEventArgs e) { if (e.ScrollOrientation == ScrollOri ...
- mysql数据库delete数据时不支持表别名
今天在帮同事查看一条删除的SQL语句执行出错的问题 SQL语句如下: 1 DELETE FROM LEAD_SYSTEM_MENU_ORG_REF as t WHERE t.resourceid='4 ...
- MYSQL查询某字段中以逗号分隔的字符串的方法
首先我们建立一张带有逗号分隔的字符串. CREATE TABLE test(id int(6) NOT NULL AUTO_INCREMENT,PRIMARY KEY (id),pname VARCH ...
- CentOS7.0安装JDK1.8.0_31
1.检查一下系统中的jdk版本 $>java -version java version "1.7.0_"OpenJDK Runtime Environment (IcedT ...
- VMT & DMT
虚拟方法表和动态方法表 虚拟方法表VMT: 一个虚拟方法表从指针所指地址的负偏移.76 处开始,长度动态分配(由虚拟方法的个数确定).虚拟方法表被分为很多小段,每段占4 个字节,也就是众多指针.每个指 ...
- xml结构
一.XmlHelper using System; using System.Collections.Generic; using System.Linq; using System.Web; usi ...
- SqlBulkCopy 插入100W条数据时 属性BatchSize的作用
(1)100W条insert语句在一个连接内一句一句加 花了01:17:19.0542805 (2) SqlBulkCopy 插入100W条数据 设置BatchSize=500 耗时:00:03:29 ...
- lib和dll的区别,生成(转)
首先介绍下静态库(静态链接库,.lib文件),动态库*(动态链接库,.dll文件)的概念,首先两者都是代码共享的方式. 静态库:在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件,这 ...
- 小心C语言的定义与声明
小心C语言的定义与声明 转自360博客 注:为便于说明问题,文中提及的变量和函数都被简化. 一.起源 DBProxy在测试过程中,发现对其执行某步管理操作后,程序有时会崩溃,但不是每次都出现. 二.G ...
- MVC 中的@Html.DropDownList下拉框的使用
MVC 中的下拉框 实现方式,下面为大家介绍一个我自己认为比较好用的实现方式,而二话不说直接上代码: 第一步: 后台代码 //公共的方法 //在每次需要展示下拉框的时候,需要调用一下这个方法 [数据源 ...