[sgu P155] Cartesian Tree
155. Cartesian Tree
memory limit per test: 65536 KB
output: standard output
That is, if we denote the left subtree of the node x by L(x), its right subtree by R(x) and its key by kx, for each node x we will have
* if y in L(x) then ky < kx
* if z in R(x) then kz > kx
The binary search tree is called cartesian if its every node x in addition to the main key kx also has an auxiliary key that we will denote by ax, and for these keys the heap condition is satisfied, that is
* if y is the parent of x then ay < ax
Thus a cartesian tree is a binary rooted ordered tree, such that each of its nodes has a pair of two keys (k, a) and three conditions described are satisfied.
Given a set of pairs, construct a cartesian tree out of them, or detect that it is not possible.
If there are several possible trees, output any one.
5 4
2 2
3 9
0 5
1 3
6 6
4 11
2 3 6
0 5 1
1 0 7
5 0 0
2 4 0
1 0 0
3 0 0
cartesian tree,俗称“笛卡尔树”。
笛卡尔树是什么呢?就是一颗类treap树。
即每个节点有两个域值,一个阈值满足二叉排序树性质,另一个域值满足堆性质。
首先说一下,笛卡尔树和treap结构上相似,但实际上,treap的第二个阈值只是用于维护平衡,而笛卡尔树的阈值是真正的值。
这道题目主要是笛卡尔树的建树。
它是O(n)的(核心部分)。
我们先把所有节点按照二叉树值从大到小排序,并假设现在已经建成了一个1~i-1的节点的树。
那么当前节点i按照二叉树值插入一点会插入在最右链的末端。
不过这样,可能会使其父节点的堆值大于他。怎么办?我们相当于做一个左旋操作。
找到第一个堆值比i小的i的祖先u,使i成为u的右儿子,u原来的右子树变为u的左子树,这样就可以满足要求了,并且这样的树一定是存在的。
那么,现在的问题是,怎样找到u?显然,可以二分查找O(nlogn)的复杂度。但这样不是最优的。
最优的就是就是用一个单调栈,记录最右链的节点。由于每一个节点最多访问一次,所以复杂度是O(n)的。
code:
#include<bits/stdc++.h>
using namespace std;
,inf=0x1a1a1a1a;
int n,s[N],top;
struct node {int k,x,i,f,l,r;}a[N];
bool cmp_k(const node &u,const node &v) {return u.k<v.k;}
bool cmp_i(const node &u,const node &v) {return u.i<v.i;}
int main() {
cin>>n,top=;
; i<=n; i++)
scanf("%d%d",&a[i].k,&a[i].x),a[i].i=i;
a[].l=a[].r=a[].i=,a[].k=a[].x=-inf;
sort(a+,a++n,cmp_k);
s[++top]=;
,las=-; i<=n; i++,las=-) {
while (top&&a[s[top]].x>a[i].x) las=s[top],top--;
a[i].f=a[s[top]].i,a[s[top]].r=a[i].i;
if (~las) a[i].l=a[las].i,a[las].f=a[i].i;
s[++top]=i;
}
sort(a+,a++n,cmp_i);
puts("YES");
; i<=n; i++)
printf("%d %d %d\n",a[i].f,a[i].l,a[i].r);
;
}
[sgu P155] Cartesian Tree的更多相关文章
- SGU 155.Cartesian Tree
时间限制:0.25s 空间限制:6M 题意: 给出n(n< 50000)个含双关键字(key,val)的节点,构造一颗树使该树,按key值是一颗二分查找树,按val值是一个小根堆. Soluti ...
- Algorithm: cartesian tree
http://baike.baidu.com/link?url=XUt5fXQ-jtFBM0UdKiGA41_NWFvdFSYwVsy4SVvCRRuEBvNkLfT9TgOtzsXvaOT9nuq_ ...
- 笛卡尔树Cartesian Tree
前言 最近做题目,已经不止一次用到笛卡尔树了.这种数据结构极为优秀,但是构造的细节很容易出错.因此写一篇文章做一个总结. 笛卡尔树 Cartesian Tree 引入问题 有N条的长条状的矩形,宽度都 ...
- PAT-2019年冬季考试-甲级 7-4 Cartesian Tree (30分)(最小堆的中序遍历求层序遍历,递归建树bfs层序)
7-4 Cartesian Tree (30分) A Cartesian tree is a binary tree constructed from a sequence of distinct ...
- Day6 - J - Cartesian Tree POJ - 2201
Let us consider a special type of a binary search tree, called a cartesian tree. Recall that a binar ...
- PAT-1167(Cartesian Tree)根据中序遍历序列重建最小堆
Cartesian Tree PAT-1167 一开始我使用数组进行存储,但是这样可能会导致无法开足够大的数组,因为树如果是链表状的则无法开这么大的数组(虽然结点很少). 正确的解法还是需要建树,使用 ...
- POJ 2201 Cartesian Tree ——笛卡尔树
[题目分析] 构造一颗笛卡尔树,然后输出这棵树即可. 首先进行排序,然后用一个栈维护最右的树的节点信息,插入的时候按照第二关键字去找,找到之后插入,下面的树成为它的左子树即可. 然后插入分三种情况讨论 ...
- OpenJudge Cartesian Tree
[代码] #include <cstdio> #include <cstdlib> #include <cstring> #include <algorith ...
- CF1290E Cartesian Tree
考虑笛卡尔树的意义: 一个点在笛卡尔树中的子树,代表以他为最小/最大值的区间. 所以一个点的子树大小,一定是类似到达序列边界或者被一个比他更大的数隔离. 考虑记录 \(l_i,r_i\) 为第 \(i ...
随机推荐
- mongodb 使用mongodump备份 指定用户名密码 出现错误 Failed: error connecting to db server: server returned error on SASL authentication step: Authentication failed
mongodb 使用mongodump备份 指定用户名密码 出现错误 [root@MongoDB ~]# mongodump --host -u admin -p -d db1 -o /root/ F ...
- SLAM领域牛人、牛实验室、牛研究成果梳理
点击公众号"计算机视觉life"关注,置顶星标更快接收消息! 本文阅读时间约5分钟 对于小白来说,初入一个领域时最应该了解的当然是这个领域的研究现状啦.只有知道这个领域大家现在正在 ...
- Android adt-bundle 开发环境的搭建_windows
本文完全拷贝的是: https://www.jb51.net/article/87953.htm 的文章仅仅用于自己保存学习消息. Android开发环境有三种方式,分别是JDK+SDK+Ecli ...
- 54.超大数据快速导入MySQL
超大数据快速导入MySQL ----千万级数据只需几十分钟本地测试方法1.首先需要修改本地mysql的编码和路径,找到my.ini.2.在里面添加或修改 character-set-server=u ...
- 一个不错的git资源站点
https://backlog.com/git-tutorial/cn/stepup/stepup2_8.html
- Python记录12:迭代器+生成器+生成式
'''1. 什么是迭代器 什么是迭代:迭代就是一个重复的过程,但是每一次重复都是基于上一次的结果而进行的 单纯的重复不是迭代: while True: print(1) 迭代的过程 l=['a','b ...
- Python之包管理
1.setup.py from distutils.core import setup setup(name='Distutils', version='1.0', description='Pyth ...
- Linux基础命令---lpc打印机控制
lpc lpc指令用来控制打印机,它提供了一个命令行,用户可以输出命令来控制打印机.如果命令行上没有指定命令,lpc将从标准输入中显示提示符并接受命令. 此命令的适用范围:RedHat.RHEL.Ub ...
- GO语言常量和变量
标识符与关键字 标识符 人为定义有特殊意义的词,Go语言中标识符由字母数字和_(下划线)组成,并且只能以字母和_开头. 关键字 关键字是指编程语言中预先定义好的具有特殊含义的标识符. GO语言中有25 ...
- js实现复制内容到剪切板,兼容pc和手机端,支持Safari浏览器
Javascript原生有一些事件:copy.paste.cut, 这些事件可以作用的目标元素: 能获得焦点的元素 (如contentEditable内容能编辑或者可以选中的元素),或者是<bo ...