前言

最近做题目,已经不止一次用到笛卡尔树了。这种数据结构极为优秀,但是构造的细节很容易出错。因此写一篇文章做一个总结。

笛卡尔树 Cartesian Tree

引入问题

有N条的长条状的矩形,宽度都为1,第i条高度为Hi,相邻的竖立在x轴上,求最大的子矩形面积。

约定

1 ≤ N ≤ 105

1 ≤ Hi ≤ 109

分析

我们只需要求出每条矩形最多可以向两边拓展的宽度,就可以算出以这个矩形高度为高的最大子矩形面积。最后我们求一个最大值即可。

下面我们还是回到之前的笛卡尔树。

概念

笛卡尔树的树根是这一子树中键值最小(或最大)的元素;且对于某个序列的笛卡尔树,其任一子树的中序遍历恰好是对应了原序列中的一段连续区间。

性质

我们会发现笛卡尔树同时满足二叉树搜索和堆的性质:

  1. 中序遍历即为原数组序列
  2. 父节点的键值均小于(或大于)其左右子节点的键值

构造

我们可以利用单调栈在线性时间内对给定的数组序列构造出其笛卡尔树。

首先,由于笛卡尔树的中序遍历为原数组序列,那么我们设

Ti为当前序列中[1..i]区间的笛卡尔树,

那么,一定有:

第(i+1)个节点属于Ti最右边的那一条路径。

那么对于有已经构造好的Ti和第(i+1)个节点,我们只需要沿着Ti最右边的路径从下往上找,直到发现当前节点可以放的位置。

我们可以用一个单调栈来维护最右边的这条路径,当前根节点压在栈底,对于当前节点,我们将它与栈顶比较,若栈顶不能做它的父节点,则将栈顶弹出。

由于每个点进栈和出栈至多一次,因此这个构造的复杂度为O(n)的。

参考代码

节点用结构体定义

(这里我们用指针会方便许多)

struct Node {
int index, val; // index表示原数组的索引,val为当前节点的键值
Node *parent, *lefts, *rights; // 这三个指针分别指向父节点,左子节点,右子节点
Node(int id = , int v = , Node *l = NULL, Node *r = NULL) { index = id; val = v; lefts = l; rights = r; }
};

树构造函数

(这里要注意的细节较多)

Node * build(int arr[], int size) {    // 这里构建一个根节点为最小值的笛卡尔树
std::stack<Node * > S; // 存储最右边路径的栈
Node *now, *next, *last;
for (int i = ; i < size; i++) {
next = new Node(i, arr[i]); last = NULL; // last用来指向最后被弹出栈的元素(若有弹出),它的作用后面会写到
while (!S.empty()) {
if (S.top()->val < next->val) { // 若栈顶节点的键值比当前节点键值小了,那么当前节点就做栈顶节点的右子节点
now = S.top();
if (now->rights) { // 而栈顶节点的原右子节点要变成当前节点的左子节点(由于前面一定与当前节点比较过了,栈顶节点右子树的键值一定都比当前节点大)
now->rights->parent = next;
next->lefts = now->rights;
}
now->rights = next;
next->parent = now;
break;
}
last = S.top();
S.pop();
}
if (S.empty() && last) { // 这里为了特判一种可能出现的情况,就是当前节点把栈全部弹空了,就要把原先的根节点作为当前节点的左子节点
next->lefts = last;
last->parent = next;
}
S.push(next);
}
while (!S.empty()) now = S.top(), S.pop();
return now;
}

笛卡尔树Cartesian Tree的更多相关文章

  1. [模板] 笛卡尔树 && RMQ

    话说我noip之前为什么要学这种东西... 简介 笛卡尔树(Cartesian Tree) 是一种二叉树, 且同时具有以下两种性质: 父亲节点的值大于/小于子节点的值; 中序遍历的结果为原序列. 笛卡 ...

  2. POJ 2201 Cartesian Tree ——笛卡尔树

    [题目分析] 构造一颗笛卡尔树,然后输出这棵树即可. 首先进行排序,然后用一个栈维护最右的树的节点信息,插入的时候按照第二关键字去找,找到之后插入,下面的树成为它的左子树即可. 然后插入分三种情况讨论 ...

  3. NOIP2011pj表达式的值[树形DP 笛卡尔树 | 栈 表达式解析]

    题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × ...

  4. 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)

    在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...

  5. [乱搞]hdu 6406 Taotao picks apples 笛卡尔树+倍增

    题目链接 Problem Description There is an apple tree in front of Taotao's house. When autumn comes, n app ...

  6. Codeforces Round #114 (Div. 1) D. Wizards and Roads 笛卡尔树+树贪心+阅读题

    D. Wizards and Roads 题目连接: http://www.codeforces.com/contest/167/problem/D Description In some count ...

  7. 笛卡尔树 POJ ——1785 Binary Search Heap Construction

    相应POJ 题目:点击打开链接 Binary Search Heap Construction Time Limit: 2000MS   Memory Limit: 30000K Total Subm ...

  8. HDU - 1506 Largest Rectangle in a Histogram (单调栈/笛卡尔树)

    题意:求一个直方图中最大矩形的面积. 很经典的一道问题了吧,可以用单调栈分别求出每个柱子左右两边第一个比它低的柱子(也就相当于求出了和它相连的最后一个比它高的柱子),确定每个柱子的左右边界,每个柱子的 ...

  9. POJ-1785-Binary Search Heap Construction(笛卡尔树)

    Description Read the statement of problem G for the definitions concerning trees. In the following w ...

随机推荐

  1. Docker部署Golang

    1. 安装docker 2. mkdir myDocker 3.  cd myDocker && touch Dockerfile 4.  Dockerfile写入 # 将golang ...

  2. R软件中 文本分析安装包 Rjava 和 Rwordseg 傻瓜式安装方法四部曲

    这两天,由于要做一个文本分析的内容,所以搜索了一天R语言中的可以做文本分析的加载包,但是在安装包的过程,真是被虐千百遍,总是安装不成功.特此专门写一篇博文,把整个心塞史畅快的释放一下. ------- ...

  3. 凡事不求甚解,遇事必定抓瞎——PHP开发Apache服务器配置备忘录

    照此配置流程,绝对一路畅通,可保无虞. 昨天弄了个PHP小程序,想在本地跑一下测试,可是工作电脑没有安装环境,于是下载了一个wamp,一路畅通,Apache.Mysql.PHP就全有了.启动wamp服 ...

  4. 树莓派3+rtl8812au开启monitor模式

    首先要有一块树莓派,要有一块rtl8812au的网卡. 这个网卡是支持monitor模式的,但是我原来装的驱动驱动在raspbian上开启monitor模式时提示,找不到设备. 然后换了一个驱动 ht ...

  5. 第十二周PSP

  6. Sprint会议3

    昨天:熟悉了一下软件操作,设计了图标. 今天:今天满课,没有做什么实质性的进展. 遇到问题:由于没干什么,也没遇到什么问题.

  7. WebGL七点二

    与上一节相比这一节相当做了些整合和整理,目的是提高了读写效率和减少代码量,就是做了优化.这里我们只需要在顶点着色器中定义一个用于从js传递参数的变量u_MvcMatrix一看就知道是uniform变量 ...

  8. 软工1816 · Beta冲刺(6/7)

    团队信息 队名:爸爸饿了 组长博客:here 作业博客:here 组员情况 组员1(组长):王彬 过去两天完成了哪些任务 推进Web端完成开发 推进修改一些后端接口的逻辑 着手制作视频 接下来的计划 ...

  9. beta冲刺(7/7)

    目录 组员情况 组员1:胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:恺琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:何宇恒 组员11:刘一好 展示组内最新 ...

  10. Internet History, Technology and Security (Week5.2)

    Week5 Now, I want to make it real clear that, when I give you a 15 minute video of an amazing invent ...