首页 > 其他分享 >P1377 [TJOI2011] 树的序

P1377 [TJOI2011] 树的序

时间:2024-08-23 16:50:50浏览次数:10  
标签:插入 笛卡尔 int top P1377 stk BST TJOI2011

题意

输入 \(n\) 个数字,按照顺序将这 \(n\) 个数字插入 BST,在保证 BST 的结构不变的情况下,重排插入顺序,使得其字典序最小。

思路

这个题目很好地利用了笛卡尔树的性质。

我们考虑最后建出来的 BST 的中序遍历一定是 \(1, 2, 3, \cdots , n - 1, n\),不难想到,BST 的一个子树的根节点一定是最先添加的,否则这个位置就不是它的了。

所以我们考虑建笛卡尔树,设 \(a_i\) 表示数字 \(i\) 在原插入顺序的第 \(a_i\) 位,我们将 \(a\) 数组从前往后插入笛卡尔树,这保证了其中序遍历为 \(1, 2, 3, \cdots , n - 1, n\),保证其是一个合法的 BST,并且每个数字代表的下标满足堆的性质,所以下标靠前的一定在笛卡尔树的浅层。

最后前序遍历一边即可,理由同“BST 的一个子树的根节点一定是最先添加的,否则这个位置就不是它的了”。

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;

int n, a[N];
int lc[N], rc[N];
int stk[N], top;

void dfs(int u) {
    cout << u << ' ';
    if (lc[u]) dfs(lc[u]);
    if (rc[u]) dfs(rc[u]);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        a[x] = i;
    }

    for (int i = 1; i <= n; i++) {
        int k = top;
        while (k && a[stk[k]] > a[i]) k--;
        if (k) rc[stk[k]] = i;
        if (k < top) lc[i] = stk[k + 1];
        stk[++k] = i;
        top = k;
    }

    dfs(stk[1]);
    return 0;
}

标签:插入,笛卡尔,int,top,P1377,stk,BST,TJOI2011
From: https://www.cnblogs.com/Yuan-Jiawei/p/18376388

相关文章

  • P1377 [TJOI2011] 树的序 (笛卡尔树)
    笛卡尔树模板题题目给出一个生成序列要我们构造一个二叉搜索树。所以值要满足二叉搜索树的性质。因为给出的是生成序列,所以序列的下标是满足最小堆的性质。那么可以按照满足二叉搜索树的那一维度进行排序也就是值进行排序。然后进行构建即可。最后进行先序遍历即可获得答......
  • P2065 [TJOI2011] 卡片 题解
    看大家建图时中间都连了质数点,发一个不用质数点的解法。我们可以先从源点向每一个蓝色卡片对应的点连一条边,再从每一个红色卡片对应的点向汇点连一条边。如果两张卡片可以一起拿走,那就在它们之间连一条边(蓝色连到红色),这些边的最大流量都是\(1\)。建好图以后我们就可以直接用Di......
  • P2065 [TJOI2011] 卡片
    桌子上有mm张蓝色卡片与nn张红色卡片,每张卡片上有一个大于1的整数。现在你要从桌子上拿走一些卡片,分若干次拿。每次只能拿走一组卡片:这组卡片颜色不同,并且两张卡片......