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 ...
随机推荐
- JMeter2.13 连接 sql server
1.安装驱动 http://www.microsoft.com/zh-CN/download/details.aspx?id=11774 下载最新的即可 解压后复制势穷力竭sqljdbc.jar到 “ ...
- PHP preg_replace() 正则替换所有符合条件的字符串示例
PHP preg_replace() 正则替换,与Javascript 正则替换不同,PHP preg_replace() 默认就是替换所有符号匹配条件的元素. 需要用程序处理的数据并不总是预先以数 ...
- 11)Java abstract class 和 interface
abstract class 和 interface 的区别 含有abstract修饰符的class即为抽象类,abstract 类不能创建实例对象.含有abstract方法的类必须定义 ...
- C# 常用的dialogresult reset 以及if else 等检查获取客户操作信息的操作方法
DialogResult reset; reset= MessageBox.Show("请检查您的输入信息是否按照规则输入的", "信息输入好像有问题哦", M ...
- PBOC规范(2.0->3.0)对照表
1 数据方面 TAG PBOC2.0 ...
- CA证书过期
CA证书问题请教!最近在客户这里做Exchange2010及RMS项目,对当前Ca证书颁发机构的环境做了下勘察和调研,发现有些地方出现警号显示过期,不知道会不会影响Exchange和Adrms的集成部 ...
- Java Collections Source Code Series 2 ---接口
废话开篇 自己学完Java Collections框架之后,其中的一个较大的收获就是接口对于层次的重要性.Java Collections的最终实现至少有几十个,其中很多都有非常相似的功能(metho ...
- OpenGL完整实例
结合上一节的内容,分享完整代码. 先画一个cube,然后通过OnGestureListener去触发onFling使它旋转起来. OnGestureListener相关的方法我已经都加了注释,可以参考 ...
- Spring框架中的IOC和DI的区别
上次面试被问到IOC和DI的区别时,没怎么在意,昨天又被问到,感觉有点可惜.今晚总算抽点时间,查看了spring官方文档.发现,IoC更像是一种思想,DI是一种行为.为了降低程序的耦合度,利用spri ...
- android开发系列之git常用命令
最近因为跳槽到新公司,然后新公司里面的代码管理工具是gitLab,所以我想在这篇博客里面整理一下git常用的语法. GitLab是利用 Ruby on Rails 一个开源的版本管理系统,实现一个自托 ...