笛卡尔树(Cartersian Tree)2016.9.12

来源:互联网 发布:口袋妖怪复刻源码 编辑:程序博客网 时间:2024/06/11 18:41

参考: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 第一个插入树的节点



图 5 第二个元素比树中最右边路径上的节点 1 的 val 大,故成为节点 1 的右孩子



图 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;}


1 0
原创粉丝点击