我们可以借助栈这个结构来维护这个关系。我们设这个栈就是这棵笛卡尔树的右链,每加入一个节点就先检查这个栈里面第一个比 优先级大的点,比 优先级小的点就用 while 扫把它给 pop 出栈外(因为这些都是要被加入左儿子的点,以后用不到了)。然后就修改儿子和父亲的关系。修改完了之后就把该点加入右链里面。由于每个节点都会入栈,有些节点会出栈有些节点不会出栈,那么我们就得到了一个 的做法!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
int st[N], len; //手写栈 voidbuild(){ for(int i=1;i<=n;i++){ int pos = st[len]; // 取右链的最后一个节点 while(len && tr[pos].pri < tr[i].pri){ // 当右链有节点并且最后一个节点的优先级比新增节点的优先级小 pos = tr[pos].fa; // 就跳到他的父亲。因为父亲的优先级一定比扫到的这个点的优先级大 len--; // 栈 pop 操作,把这个点 pop 出栈外 } tr[i].ls = tr[pos].rs; // 把第一个比 i 优先级大的点 pos 的右儿子插入到 i 的左儿子下 tr[tr[pos].rs].fa = i; // 对应的,设置 i 的新左儿子的父亲 tr[pos].rs = i; // 设置 pos 的右儿子为 i tr[i].fa = pos; // 对应的,设置 i 的父亲为 pos st[++len] = i; // 将节点插入栈 } }