【CF 675D Tree Construction】BST
题目链接:http://codeforces.com/problemset/problem/675/D
题意:给一个由n个互异整数组成的序列a[],模拟BST的插入过程,依次输出每插入一个元素a[i]后a[i]的父节点。
数据范围:n [2, 10^5]
思路:直接模拟一般的BST而不维护平衡性的话,有可能会出现极度不平衡甚至退化的情况,复杂度会从O(nlogn)上升到O(n^2)。因此要用平衡二叉树。
可以利用STL中的set容器,但对于题目所要找的“父节点”,set并不提供接口。这时就要考察BST的一些性质推导出解法。
回顾二叉树的中序遍历,对节点prev的直接后继succ的定位操作分两种情况。注意等价BST的“上下可变,左右不乱”的性质,不论是否进行了等价变换,中序遍历序列中任意两个互为直接前驱和直接后继的元素,其层次关系必然为如下两种之一:

1. succ层次更深
=> 由顺序性,succ必为prev的右子树中的节点,故prev的右子树必非空;
且由“直接性”,succ的左孩子必为空。
对于v小于全局最小值的边界情况,prev及其左子树为空。
2. prev层次更深
=> 由顺序性,prev必为succ的左子树中的节点,故succ的左子树必非空;
且由“直接性”,prev的右孩子必为空。
对于v大于全局最大值的边界情况,succ及其右子树为空。
对于一个新的待插入的节点v,我们在当前BST的中序遍历序列 s 中进行二分查找,得到应插入的位置的后继元素的位置succ(“大于v的第一个元素,即upper_bound”),然后得到prev=succ-1。为了保证BST的顺序性,v必然要插在prev和succ之间。
从树的结构上看,可以插在标有“必为空”的位置,它恰好介于prev和succ之间,顺序性必然得到保证。具体地,即“succ和prev中更深的那个”,1、2两种情况分别对应succ和prev。如何确定是哪种情况呢?
我们回到对这两种情况的描述上:刚刚所做的推导是否可逆呢?如果可逆,那么我们可以通过判断succ或prev的左右孩子是否为空就可以得知是哪种情况。
分析发现,确实可逆:
1. succ的左孩子为空 => 由顺序性,prev必为succ的祖先 => succ层次更深。
2. prev的右孩子为空 => 由顺序性,succ必为prev的祖先 => prev层次更深。
到此,可以着手设计算法了。首先用set维护平衡二叉树,每次插入节点v前,调用set的lower_bound(或upper_bound,元素互异故二者无差别) 得到“大于v的第一个元素”,即插入v后v的直接后继,记录为迭代器succ。然后得到succ的直接前驱的迭代器prev = succ - 1。
对于左右孩子情况的记录,我没有想到方法,CF题解给出的是维护两个map<int, int>left, right,left记录节点对<v, lc>,right记录节点对<v, rc>。每次插入前通过判断left[succ]和right[prev]是否为空来判断父节点是谁,以及v作为左孩子还是右孩子插入,更新map。
其实这两种情况是对立的,因此一次判断就可确定属于哪种。
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
using namespace std;
const int MAX_N = ; int n;
struct Node
{
int d;
int lc, rc;
Node(){}
Node(int d):d(d), lc(-), rc(-){}
}nodes[MAX_N]; int a[MAX_N]; int main()
{
while(~scanf("%d", &n)){
for(int i=; i<n; i++){
scanf("%d", &a[i]);
}
set<int> s;
map<int, int> left;//<节点,左孩子>
map<int, int> right; //<节点,右孩子>
int res;
s.insert(a[]);
for(int i=; i<n; i++){
set<int>::iterator pos = s.lower_bound(a[i]);//直接后继
if(pos != s.end() && left.count(*pos)==){//后继没有左孩子,插到后继的左孩子位置
res = *pos;
left[*pos] = a[i];
}else{//后继有左孩子,或没有后继,插到前驱的右孩子位置
pos--;
res = *pos;
right[*pos] = a[i];
}
printf("%d ", res);
s.insert(a[i]);
}
printf("\n");
}
return ;
}
p.s: CF题解的代码好优美,学习了。
【CF 675D Tree Construction】BST的更多相关文章
- CF 675D——Tree Construction——————【二叉搜索树、STL】
		
D. Tree Construction time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
 - B. Lost Number【CF交互题 暴力】
		
B. Lost Number[CF交互题 暴力] This is an interactive problem. Remember to flush your output while communi ...
 - 3.26-3.31【cf补题+其他】
		
计蒜客)翻硬币 //暴力匹配 #include<cstdio> #include<cstring> #define CLR(a, b) memset((a), (b), s ...
 - 【Binary Search Tree Iterator 】cpp
		
题目: Implement an iterator over a binary search tree (BST). Your iterator will be initialized with th ...
 - 【cf补题记录】Codeforces Round #608 (Div. 2)
		
比赛传送门 再次改下写博客的格式,以锻炼自己码字能力 A. Suits 题意:有四种材料,第一套西装需要 \(a\).\(d\) 各一件,卖 \(e\) 块:第二套西装需要 \(b\).\(c\).\ ...
 - Codeforces 675D   Tree Construction Splay伸展树
		
链接:https://codeforces.com/problemset/problem/675/D 题意: 给一个二叉搜索树,一开始为空,不断插入数字,每次插入之后,询问他的父亲节点的权值 题解: ...
 - 【Cf Edu #47 F】Dominant Indices(长链剖分)
		
要求每个点子树中节点最多的层数,一个通常的思路是树上启发式合并,对于每一个点,保留它的重儿子的贡献,暴力扫轻儿子将他们的贡献合并到重儿子里来. 参考重链剖分,由于一个点向上最多只有$log$条轻边,故 ...
 - 【Count Complete Tree Nodes】cpp
		
题目: Given a complete binary tree, count the number of nodes. Definition of a complete binary tree fr ...
 - codeforces 675D Tree Construction set
		
转自:http://blog.csdn.net/qwb492859377/article/details/51447350 #include <stdio.h> #include < ...
 
随机推荐
- 查看登录用户who
			
几个命令:wwho每隔5秒钟,就来查看hadoop是否已经登录,如登录,显示其已经登录,并退出:sleep whoami last,显示/var/log/wtmp文件,显示用户登录历史及系统重启历史 ...
 - win10无法使用内置管理员账户打开
			
对于这种问题其实对于专业版用户倒不是难事,很容易解决,具体方法如下: 首先WIN+R输入:gpedit.msc,打开组策略,找到“计算机配置”里面的“Windows设置”,打开“安全设置” -> ...
 - SQL生成随机字符串
			
1.SQLserve生成随机字符串 SELECT replace(newid(), '-', '')
 - Android NDK R9d 安装
			
NDK是一个工具集,可让您实现您的应用程序使用本机代码的语言,如C和C + +.Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Kit,因此又被Go ...
 - vim 的配色方案
			
浅色: http://www.vimninjas.com/2012/09/14/10-light-colors/ 深色: http://www.vimninjas.com/2012/08/26/10- ...
 - pyqt 同时勾选多个items(网友提供学习)
			
框选多个item之后,用空格键可以勾选/去选多个item,效果如下图所示: http://oglop.gitbooks.io/pyqt-pyside-cookbook/list/img/checkbo ...
 - 面试时如何优雅的谈论OC
			
在面试中,我们经常会遇到一些原理性的问题,很常识但很难用通俗的语言解释清楚,这也是大部分业务级程序员经常失误的地方.虽然写了多年代码,但是核心思想不清,导致自己的后续发展受限,这是一个优秀的程序员和普 ...
 - JS中for循环里面的闭包问题的原因及解决办法
			
我们先看一个正常的for循环,普通函数里面有一个for循环,for循环结束后最终返回结果数组 function box(){ var arr = []; for(var i=0;i<5;i++) ...
 - BOM 窗体相关属性以及页面可见区域的获取方式
			
1 在IE Safari Oper Chrome 都提供了screenLeft和screenTop属性: screenLeft : 相对于屏幕左边的距离 screenTop : 相对于屏幕上边的距离 ...
 - php使用session来保存用户登录信息
			
php使用session来保存用户登录信息 使用session保存页面登录信息 1.数据库连接配置页面:connectvars.php <?php //数据库的位置 define('DB_HOS ...