笛卡尔树模板
笛卡尔树,类似于 Treap,由两个键值 val 和 wt 组成。
前者满足二叉排序树性质(即中序遍历升序),后者满足堆性质。
其与 Treap 的不同之处在于 wt 值确定,而非随机生成。
val 值升序的序列可以在 O(n) 的时间内借助单调栈构造出对应的笛卡尔树,具体方法如下:
- 用单调栈维护当前树的右链(下图中蓝框所示)
- 按 val 从小到大访问每个待插入节点 u
- 弹出栈中所有 wt 值大于 u 点 wt 值的点(以小根堆为例)
- 将 u 点连在当前栈顶的右子树上
- 将被弹出的子树根连到 u 点的左子树上
提供一道模板题 POJ 2201 Cartesian Tree。
注意该题不保证 val 值升序,需要先进行排序,另外写读入优化时需要考虑键值可能为负数。
Problem:
Time Limit: 10000MS | Memory Limit: 65536K | |
Case Time Limit: 2000MS |
Description
That is, if we denote left subtree of the node x by L(x), its right subtree by R(x) and its key by kx then for each node x we have
- if y ∈ L(x) then ky < kx
- if z ∈ R(x) then kz > kx
The binary search tree is called cartesian if its every node x in addition to the main key kx also has an auxiliary key that we will denote by ax, and for these keys the heap condition is satisfied, that is
- if y is the parent of x then ay < ax
Thus a cartesian tree is a binary rooted ordered tree, such that each of its nodes has a pair of two keys (k, a) and three conditions described are satisfied.
Given a set of pairs, construct a cartesian tree out of them, or detect that it is not possible.
Input
Output
The input ensure these is only one possible tree.
Sample Input
7 5 4 2 2 3 9 0 5 1 3 6 6 4 11
Sample Output
YES 2 3 6 0 5 1 1 0 7 5 0 0 2 4 0 1 0 0 3 0 0
Source
Code: O(NlogN) [2628K, 1907MS]
// 笛卡尔树 (2018.3.2) // POJ 2201 Cartesian Tree #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; inline void getint(int &num){ char ch; bool neg = 0; while(!isdigit(ch = getchar())) if(ch == '-') neg = 1; num = ch - '0'; while(isdigit(ch = getchar())) num = num * 10 + ch - '0'; if(neg) num = -num; } int N, tops = 0; int fa[50002], lc[50002], rc[50002]; struct Node{ int id, val, wt; Node *lc, *rc, *fa; inline bool operator < (const Node &node2) const {return val < node2.val;} } CT[50002], *stk[50002]; inline Node* build(Node *CT, int Size){ for(register int i = 1; i <= Size; i++){ Node *o = NULL; while(tops && CT[i].wt < stk[tops]->wt) o = stk[tops--]; // Maintain the monotonous stack CT[i].lc = o, CT[i].fa = stk[tops]; if(o) o->fa = &CT[i]; if(stk[tops]) stk[tops]->rc = &CT[i]; // Redirect the pointers of relationship stk[++tops] = &CT[i]; } return stk[1]; } int main(){ getint(N); for(register int i = 1; i <= N; i++) getint(CT[i].val), getint(CT[i].wt), CT[i].id = i; sort(CT + 1, CT + N + 1); // BST indexes must be ascending Node *root = build(CT, N); for(register int i = 1; i <= N; i++){ fa[CT[i].id] = CT[i].fa ? CT[i].fa->id : 0; lc[CT[i].id] = CT[i].lc ? CT[i].lc->id : 0; rc[CT[i].id] = CT[i].rc ? CT[i].rc->id : 0; } puts("YES"); // Must have solution for(register int i = 1; i <= N; i++) printf("%d %d %d\n", fa[i], lc[i], rc[i]); return 0; }
发表评论