题目链接:

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的祖先和后代关系导致的),所以,真正能插入的地方就只有一个。

具体实现看代码。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<set>
  4. #include<map>
  5. #include<vector>
  6. using namespace std;
  7.  
  8. set<int> numbers;
  9. map<int, int> lef, rig;
  10.  
  11. int n;
  12. void init() {
  13. numbers.clear();
  14. lef.clear(); rig.clear();
  15. }
  16.  
  17. int main() {
  18. int v;
  19. while (scanf("%d", &n) == && n) {
  20. init();
  21. scanf("%d", &v);
  22. numbers.insert(v);
  23. vector<int> ans;
  24. for (int i = ; i < n - ; i++) {
  25. scanf("%d", &v);
  26. set<int>::iterator it = numbers.upper_bound(v);
  27. if (it != numbers.end() && lef[*it]==) {
  28. ans.push_back(*it);
  29. lef[*it] = ;
  30. }
  31. else {
  32. it--;
  33. ans.push_back(*it);
  34. rig[*it] = ;
  35. }
  36. numbers.insert(v);
  37. }
  38. for (int i = ; i < ans.size()-; i++) printf("%d ", ans[i]);
  39. printf("%d\n", ans[ans.size() - ]);
  40. }
  41. return ;
  42. }

贴一个avl模板代替set操作:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<set>
  4. #include<map>
  5. #include<vector>
  6. using namespace std;
  7.  
  8. const int INF = 1e9+;
  9.  
  10. //AVL树节点信息
  11. class TreeNode
  12. {
  13. public:
  14. TreeNode() :lson(NULL), rson(NULL), freq(), hgt() {}
  15. int data;//值
  16. int hgt;//高度
  17. unsigned int freq;//频率
  18. TreeNode* lson;//指向左儿子的地址
  19. TreeNode* rson;//指向右儿子的地址
  20. };
  21. //AVL树类的属性和方法声明
  22. class AVLTree
  23. {
  24. private:
  25. TreeNode* root;//根节点
  26. void insertpri(TreeNode* &node,int x,int &pre,int &aft);//插入
  27. int height(TreeNode* node);//求树的高度
  28. void SingRotateLeft(TreeNode* &k2);//左左情况下的旋转
  29. void SingRotateRight(TreeNode* &k2);//右右情况下的旋转
  30. void DoubleRotateLR(TreeNode* &k3);//左右情况下的旋转
  31. void DoubleRotateRL(TreeNode* &k3);//右左情况下的旋转
  32. int Max(int cmpa, int cmpb);//求最大值
  33. public:
  34. AVLTree() :root(NULL) {}
  35. void insert(int x,int &pre,int &aft);//插入接口
  36. };
  37. //计算节点的高度
  38. int AVLTree::height(TreeNode* node)
  39. {
  40. if (node != NULL)
  41. return node->hgt;
  42. return -;
  43. }
  44. //求最大值
  45. int AVLTree::Max(int cmpa, int cmpb)
  46. {
  47. return cmpa>cmpb ? cmpa : cmpb;
  48. }
  49. //左左情况下的旋转
  50. void AVLTree::SingRotateLeft(TreeNode* &k2)
  51. {
  52. TreeNode* k1;
  53. k1 = k2->lson;
  54. k2->lson = k1->rson;
  55. k1->rson = k2;
  56.  
  57. k2->hgt = Max(height(k2->lson), height(k2->rson)) + ;
  58. k1->hgt = Max(height(k1->lson), k2->hgt) + ;
  59. k2 = k1;
  60. }
  61. //右右情况下的旋转
  62. void AVLTree::SingRotateRight(TreeNode* &k2)
  63. {
  64. TreeNode* k1;
  65. k1 = k2->rson;
  66. k2->rson = k1->lson;
  67. k1->lson = k2;
  68.  
  69. k2->hgt = Max(height(k2->lson), height(k2->rson)) + ;
  70. k1->hgt = Max(height(k1->rson), k2->hgt) + ;
  71. k2 = k1;
  72. }
  73. //左右情况的旋转
  74. void AVLTree::DoubleRotateLR(TreeNode* &k3)
  75. {
  76. SingRotateRight(k3->lson);
  77. SingRotateLeft(k3);
  78. }
  79. //右左情况的旋转
  80. void AVLTree::DoubleRotateRL(TreeNode* &k3)
  81. {
  82. SingRotateLeft(k3->rson);
  83. SingRotateRight(k3);
  84. }
  85. //插入
  86. void AVLTree::insertpri(TreeNode* &node, int x,int &pre,int &aft)
  87. {
  88. if (node == NULL)//如果节点为空,就在此节点处加入x信息
  89. {
  90. node = new TreeNode();
  91. node->data = x;
  92. return;
  93. }
  94. if (node->data>x)//如果x小于节点的值,就继续在节点的左子树中插入x
  95. {
  96. aft = node->data;
  97. insertpri(node->lson, x,pre,aft);
  98. if ( == height(node->lson) - height(node->rson))
  99. if (x<node->lson->data)
  100. SingRotateLeft(node);
  101. else
  102. DoubleRotateLR(node);
  103. }
  104. else if (node->data<x)//如果x大于节点的值,就继续在节点的右子树中插入x
  105. {
  106. pre = node->data;
  107. insertpri(node->rson, x,pre,aft);
  108. if ( == height(node->rson) - height(node->lson))//如果高度之差为2的话就失去了平衡,需要旋转
  109. if (x>node->rson->data)
  110. SingRotateRight(node);
  111. else
  112. DoubleRotateRL(node);
  113. }
  114. else ++(node->freq);//如果相等,就把频率加1
  115. node->hgt = Max(height(node->lson), height(node->rson)) + ;
  116. }
  117. //插入接口
  118. void AVLTree::insert(int x,int &pre,int &aft)
  119. {
  120. insertpri(root, x,pre,aft);
  121. }
  122.  
  123. map<int, int> lef, rig;
  124.  
  125. int n;
  126. void init() {
  127. lef.clear(); rig.clear();
  128. }
  129.  
  130. int main() {
  131. int v,pre,aft;
  132. while (scanf("%d", &n) == && n) {
  133. AVLTree tree;
  134. init();
  135. scanf("%d", &v);
  136. tree.insert(v, pre, aft);
  137. vector<int> ans;
  138. for (int i = ; i < n - ; i++) {
  139. scanf("%d", &v);
  140. pre = , aft = INF;
  141. tree.insert(v, pre, aft);
  142. //printf("pre:%d,aft:%d\n", pre, aft);
  143. if (aft!=INF && lef[aft] == ) {
  144. ans.push_back(aft);
  145. lef[aft] = ;
  146. }
  147. else {
  148. ans.push_back(pre);
  149. rig[pre] = ;
  150. }
  151. }
  152. for (int i = ; i < ans.size() - ; i++) printf("%d ", ans[i]);
  153. printf("%d\n", ans[ans.size() - ]);
  154. }
  155. return ;
  156. }

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. JMeter2.13 连接 sql server

    1.安装驱动 http://www.microsoft.com/zh-CN/download/details.aspx?id=11774 下载最新的即可 解压后复制势穷力竭sqljdbc.jar到 “ ...

  2. PHP preg_replace() 正则替换所有符合条件的字符串示例

    PHP preg_replace() 正则替换,与Javascript 正则替换不同,PHP preg_replace() 默认就是替换所有符号匹配条件的元素.  需要用程序处理的数据并不总是预先以数 ...

  3. 11)Java abstract class 和 interface

    abstract class 和 interface 的区别        含有abstract修饰符的class即为抽象类,abstract 类不能创建实例对象.含有abstract方法的类必须定义 ...

  4. C# 常用的dialogresult reset 以及if else 等检查获取客户操作信息的操作方法

    DialogResult reset; reset= MessageBox.Show("请检查您的输入信息是否按照规则输入的", "信息输入好像有问题哦", M ...

  5. PBOC规范(2.0->3.0)对照表

    1    数据方面 TAG                                               PBOC2.0                                 ...

  6. CA证书过期

    CA证书问题请教!最近在客户这里做Exchange2010及RMS项目,对当前Ca证书颁发机构的环境做了下勘察和调研,发现有些地方出现警号显示过期,不知道会不会影响Exchange和Adrms的集成部 ...

  7. Java Collections Source Code Series 2 ---接口

    废话开篇 自己学完Java Collections框架之后,其中的一个较大的收获就是接口对于层次的重要性.Java Collections的最终实现至少有几十个,其中很多都有非常相似的功能(metho ...

  8. OpenGL完整实例

    结合上一节的内容,分享完整代码. 先画一个cube,然后通过OnGestureListener去触发onFling使它旋转起来. OnGestureListener相关的方法我已经都加了注释,可以参考 ...

  9. Spring框架中的IOC和DI的区别

    上次面试被问到IOC和DI的区别时,没怎么在意,昨天又被问到,感觉有点可惜.今晚总算抽点时间,查看了spring官方文档.发现,IoC更像是一种思想,DI是一种行为.为了降低程序的耦合度,利用spri ...

  10. android开发系列之git常用命令

    最近因为跳槽到新公司,然后新公司里面的代码管理工具是gitLab,所以我想在这篇博客里面整理一下git常用的语法. GitLab是利用 Ruby on Rails 一个开源的版本管理系统,实现一个自托 ...