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 ...
随机推荐
- 小菜的系统框架界面设计-灰姑娘到白雪公主的蜕变(工具条OutLookBar)
灰姑娘本身也有自已的优点,但是却可能因为外貌不讨人喜欢,要变成白雪公主却需要有很多勇气和决心去改变自已: 有一颗善良的心 讨人喜爱的外貌 --蜕变--> 我这里讲的是一个工具条的蜕变过程, ...
- 转:浅谈关于b、h标签的优化技巧
<b>标签优化 <b>标签是一种加粗标记,作用就是加粗文章中的关键词,对于文章中重要的关键词加粗起到有利于用户阅读的作用.<b>标签的使用对于优化的作用是非常大的, ...
- mysql 根据生日计算年龄,并查询在18-25之间的语句
select id, DATE_FORMAT(birthday,"%Y-%m-%d") birthday, CURDATE() , (year(now())-year(birthd ...
- 生产WCF客户端类文件的命令格式
生产WCF客户端类文件的命令格式: svcutil.exe net.tcp://127.0.0.1:8732/ChromaMI.Remote.ConfigService/RemoteConfigSer ...
- 第四章 管理程序流(In .net4.5) 之 事件和回调
1. 概述 本章讲解如何使用 委托.lambda表达式 和 匿名方法 来创建和使用事件. 2. 主要内容 2.1 理解委托 委托是一种用方法签名形式定义的类型.可以让它指向其他方法,可以通过它调用其他 ...
- Pure扩展站--个人博客
作为自己css的练习站:http://1111.oyostar.com/.更新自己扩展pure写的css,外加一些jquery的插件.感谢朋友的空间和子域名!
- Huffman树的编码译码
上个学期做的课程设计,关于Huffman树的编码译码. 要求: 输入Huffman树各个叶结点的字符和权值,建立Huffman树并执行编码操作 输入一行仅由01组成的电文字符串,根据建立的Huffma ...
- .NET开源工作流RoadFlow-流程设计-流转条件设置(路由)
当一个步骤后面有多个步骤时,可以设置为根据设置条件系统自动判断该流向哪些步骤,也叫路由. roadflow没有单独的路由步骤来设置条件,流程条件通过双击连线弹出条件设置框来设置. 1.sql条件 即通 ...
- Android--Fragment的懒加载
我们都知道,fragment放在viewPager里面,viewpager会帮我们预先加载一个,但是当我们要看fragment里面的内容时,我们也许只会去看第一个,不会去看第二个,如果这时候不去实现f ...
- IBM MQ扩大队列最大消息长度
要设置MQ的最大消息长度,需要考虑同时设置队列管理,队列以及通道的最大消息长度. 具体操作如下: runmqsc 队列管理器名称 alter qmgr maxmsgl(10000000) 1 : al ...