POJ 2201 Cartesian Tree 笛卡尔树裸题加讲解

来源:互联网 发布:编程软件cimit怎么样 编辑:程序博客网 时间:2024/05/19 02:26

题目:

http://poj.org/problem?id=2201

题意:

给出一个n,在给出n对数(且命名为x,y),构建一棵树,满足以下条件:

  • 对树上任意一个节点,有x > leftson_x 且x > rigthson_x
  • 对树上任意一个节点,有y > father_y

构建完成后,输出每个点的父节点,左子节点,右子节点,没有的以0代替

思路:

笛卡尔树模板题。笛卡尔树每个节点有两个值,且称为val和pri,满足以下条件:

  1. 满足任意节点的val,大于其左子节点的val,小于其右子节点的val。
  2. 满足任意节点的pri,要么全部小于其父节点的pri,要么全部大于其父节点的pri,视题目有所不同,此题是第二种情况。

可以在O(n)的时间内构建一颗笛卡尔树(此处按pri的第二种情况建树)。首先对所有节点按val从小到大排序,然后维护一个单调栈,栈中元素的pri从栈底到栈顶依次递增,这个栈实际上维护的是树的最右链,每次有新元素加入时,从栈顶向栈底遍历,栈中元素的pri大于新元素的pri的话,就直接出栈,直到遇到栈中一个元素的pri小于新元素的pri,那么把这个新元素挂到这个栈中元素的右儿子上,把刚刚出栈的最后一个元素挂到新元素的左儿子上,可以发现这样是满足建树的条件1。就这样一直进行下去,到最后,栈底的元素就是笛卡尔树的树根。
此题用treap会TLE

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int N = 50000 + 10, INF = 0x3f3f3f3f;int root;struct node{    int val, pri, fat, id, son[2];    friend bool operator< (node a, node b)    {        return a.val < b.val;    }    void init(int _val, int _pri, int _fat, int _id)    {        val = _val, pri = _pri, fat = _fat, id = _id;        son[0] = son[1] = 0;    }}tr[N];int stk[N], top;int ans_fat[N], ans_l[N], ans_r[N];int cartesian_build(int n){    top = 0;    for(int i = 1; i <= n; i++)    {        int k = top;        while(k > 0 && tr[stk[k-1]].pri > tr[i].pri) k--;//栈中元素的pri大于新元素的pri就直接出栈        if(k != 0) //栈中还有元素,就把新元素挂到这个元素的右儿子上        {            tr[i].fat = stk[k-1];            tr[stk[k-1]].son[1] = i;//            ans_fat[tr[i].id] = tr[stk[k-1]].id; //注释的这些去掉就不用dfs了,只不过为了熟悉笛卡尔树所以又写了个dfs求答案//            ans_r[tr[stk[k-1]].id] = tr[i].id;        }        if(k != top) //有元素出栈,则把出栈的最后一个元素挂到新元素的左儿子上        {            tr[stk[k]].fat = i;            tr[i].son[0] = stk[k];//            ans_fat[tr[stk[k]].id] = tr[i].id;//            ans_l[tr[i].id] = tr[stk[k]].id;        }        stk[k++] = i;        top = k;    }    return stk[0];}void dfs(int x, int fat){    if(! x) return;    ans_fat[tr[x].id] = tr[fat].id;    ans_l[tr[x].id] = tr[tr[x].son[0]].id;    ans_r[tr[x].id] = tr[tr[x].son[1]].id;    dfs(tr[x].son[0], x);    dfs(tr[x].son[1], x);}int main(){    int n;    while(~ scanf("%d", &n))    {        int a, b;        tr[0].init(0, 0, 0, 0);        for(int i = 1; i <= n; i++)        {            scanf("%d%d", &a, &b);            tr[i].init(a, b, 0, i);        }        sort(tr + 1, tr + 1 + n);        root = cartesian_build(n);        dfs(root, 0);        puts("YES");        for(int i = 1; i <= n; i++) printf("%d %d %d\n", ans_fat[i], ans_l[i], ans_r[i]);    }    return 0;}
原创粉丝点击