参考:http://blog.csdn.net/zh_qd1014/article/details/6879083(非常值得一看哦
一、
笛卡尔树是一棵二叉树,树的每个节点有两个值,一个为 key,一个为 val
光看 key 的话,笛卡尔树是一棵二叉搜索树,每个节点的左子树的 key 都比它小,右子树都比它大
光看 value 的话,笛卡尔树有点类似堆,根节点的 val是最小(或者最大)的,每个节点的 value 都比它的子树要小(或者大)
二、树的构造
如果 key 值是有序的,那么笛卡尔树的构造是线性的
如果我们要用数组 A[1 ... n] 构造出一棵有 n 个节点的笛卡尔树
为了方便理解,不妨假设每个节点的 key 为数组元素的下标 i,val 为 A[i] 来建树,这样也保证了 key 的有序性
再假设这里的笛卡尔树为一种特殊的最小堆,那么树的根节点是数组 A 中最小元素的下标 i,根节点的左右孩子分别由数组 A[1 ... i-1] 和数组 A[i+1 ... n] 构造
图 1 原数组
图 2 笛卡尔树最终生成结果(节点内容:key 即数组元素下标)(中序遍历可得到原数组)
图 3 笛卡尔树最终生成结果(节点内容:val 即数组元素)
图 4 第一个插入树的节点
图 6 第三个元素的 val 比树中最右边路径上节点 1、2 的 val 都小,将节点 1 设为该节点的左孩子
图 7 第四个元素的 val 比树中最右边路径上节点 3 的 val 大,故成为根节点 3 的右孩子
图 8 第五个节点元素的 val 比树中最右边的路径上的节点 3、4 的 val 都大,故成为节点 4 的右孩子
图 9 第六个节点元素的 val 比树中最右边路径上节点 5 的 val 小,但比节点 4 的 val 大,故成为节点 4 的右孩子,将节点 5 设为该节点的左孩子
图 10 第七个元素的 val 比树中最右边路径上节点 6 的 val 大,故成为节点6的右孩子
图 11 第八个元素的 val 比树中最右边路径上节点 7 的 val 小,但比节点 6 的 val 大,故该节点称为节点 6 的右孩子,节点 7 成为该节点的左孩子
图 12 第九个元素的 val 比树中最右边路径上节点 8 的 val 大,故成为节点 8 的右孩子
图 13 第十个元素的 val 比树中最右边路径上的节点 9、8、6、4 的 val 都小,但比节点 3 的 val 大,故成为节点 3 的右孩子,节点 4 成为该节点的左孩子
构造过程中需要用栈维护笛卡尔树的一条右链,即根结点、根结点的右儿子、根结点的右儿子的右儿子 …… 组成的链,注意这些元素的 key 和 val 都是递增的
每个节点最多入栈、出栈一次,因此时间复杂度为 O(n)
SGU 155 Cartesian Tree
POJ 2201 Cartesian Tree
题意:
建好笛卡尔树后输出每个结点(按照输入的顺序编号)的父亲结点和两个儿子节点的编号
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 5e4 + 10;
struct Cartesian {
int id, key, val, pre, lson, rson;
bool operator < (const Cartesian& a) const {
return key < a.key;
}
};
Cartesian tree[maxn];
stack<int> Stack;
int N;
int pos[maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%d", &N);
for (int i = 1; i <= N; ++i) {
tree[i].pre = tree[i].lson = tree[i].rson = 0;
}
for (int i = 1; i <= N; ++i) {
tree[i].id = i;
scanf("%d %d", &tree[i].key, &tree[i].val);
}
sort(tree+1, tree+1+N);
pos[tree[1].id] = 1;
Stack.push(1);
for (int i = 2; i <= N; ++i) {
pos[tree[i].id] = i;
int father = 0, son = 0;
while (!Stack.empty()) {
int t = Stack.top();
if (tree[i].val > tree[t].val) {
father = t;
break;
}
son = t;
Stack.pop();
}
tree[i].pre = father;
tree[father].rson = i;
tree[i].lson = son;
tree[son].pre = i;
Stack.push(i);
}
printf("YES\n");
for (int i = 1; i <= N; ++i) {
int pos_t = pos[i];
printf("%d %d %d\n", tree[tree[pos_t].pre].id, tree[tree[pos_t].lson].id, tree[tree[pos_t].rson].id);
}
return 0;
}
HDU 1506 Largest Rectangle in a Histogram
POJ 2559 Largest Rectangle in a Histogram
参考:http://blog.csdn.net/ophunter_lcm/article/details/9327235
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e5 + 10;
struct Cartesian {
ll val, pre, lson, rson;
};
Cartesian tree[maxn];
ll Stack[maxn];
ll n;
ll ans = 0;
ll build(void);
ll dfs(ll root);
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
while (scanf("%I64d", &n) != EOF && n != 0) {
for (ll i = 1; i <= n; ++i) {
tree[i].pre = tree[i].lson = tree[i].rson = 0;
}
for (ll i = 1; i <= n; ++i) {
scanf("%I64d", &tree[i].val);
}
ll root = build();
ans = 0;
dfs(root);
printf("%I64d\n", ans);
}
return 0;
}
ll build(void)
{
ll size = 0;
Stack[++size] = 1;
for (ll i = 2; i <= n; ++i) {
ll father = 0, son = 0;
while (size != 0) {
ll top = Stack[size];
if (tree[i].val > tree[top].val) {
father = top;
break;
}
son = top;
--size;
}
tree[i].pre = father;
tree[father].rson = i;
tree[i].lson = son;
tree[son].pre = i;
Stack[++size] = i;
}
return Stack[1];
}
ll dfs(ll root)
{
if (root == 0) {
return 0;
}
ll num = dfs(tree[root].lson) + dfs(tree[root].rson) + 1;
ll ans_t = num * tree[root].val;
if (ans_t > ans) {
ans = ans_t;
}
return num;
}