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,满足以下条件:
- 满足任意节点的val,大于其左子节点的val,小于其右子节点的val。
- 满足任意节点的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;}
阅读全文
0 0
- POJ 2201 Cartesian Tree 笛卡尔树裸题加讲解
- POJ-2201 Cartesian Tree【笛卡尔树】
- POJ 2201 Cartesian Tree 笛卡尔树
- POJ 2201 Cartesian Tree 【笛卡尔树】
- POJ 2201 Cartesian Tree (笛卡尔树)
- POJ-2201-Cartesian Tree(笛卡尔树)
- POJ 2201 Cartesian Tree 笛卡尔树
- POJ-2201 Cartesian Tree(笛卡尔树)
- poj 2201 Cartesian Tree 笛卡尔树
- 笛卡尔树cartesian tree
- 笛卡尔树(Cartesian Tree)
- SGU 155 Cartesian Tree(笛卡尔树)
- poj 北大oj 2201 Cartesian Tree
- sgu 155 Cartesian Tree (poj2201) 笛卡尔树构造
- RDD笛卡尔操作Cartesian
- poj 2201 笛卡尔树
- poj 2201 笛卡尔树
- poj 2201 笛卡尔树
- HDU2602 Bone Collector(01背包模板 一维数组)
- Hive入门
- stm32外部晶振非8MHz时的修改为8MHz
- spring组件扫描包component-scan
- 关于Maxpooling层的求导
- POJ 2201 Cartesian Tree 笛卡尔树裸题加讲解
- 剑指Offer:表示数值的字符串
- js的闭包的理解
- STL之序列式容器
- 编程练习2(一)
- 带权并查集 向量并查集 poj1182 食物链
- HDU 1251 统计难题(字典树,map)
- MyEclipse Spring开发教程:用Spring创建iPhone App(2/2)
- CVPR2017_Papers下载爬虫程序