acwing 4279. 笛卡尔树 题解

题目

笛卡尔树 是由一系列不同数字构成的二叉树。

树满足堆的性质,中序遍历返回原始序列。
最小笛卡尔树表示满足小根堆性质的笛卡尔树。

例如,给定序列 {8,15,3,4,1,5,12,10,18,6},则生成的最小堆笛卡尔树如图所示。

6a99f68a-6578-46e0-9232-fbf0adf3691f.jpg

现在,给定一个长度为 N 的原始序列,请你生成最小堆笛卡尔树,并输出其层序遍历序列。

输入格式
第一行包含整数 N。

第二行包含 N 个两两不同的整数,表示原始序列。

输出格式
共一行,输出最小堆笛卡尔树的层序遍历序列。

数据范围
1≤N≤30,
原始序列中元素的取值范围 [−2147483648,2147483647]。

输入样例:
10
8 15 3 4 1 5 12 10 18 6
输出样例:
1 3 5 8 4 6 15 10 12 18

题目的大致意思就是指,首先找到最小的数字,然后以这个数字为一个节点,寻找左右两边最小的数字,然后将他们分别作为左右节点,然后一直持续下去,由于是左右,所以当最小的数字处于边界的时候,就不会产生两个分支,而是一个

由此我们,只需要无限递归就可以了,每次递归下去的是下一个的左边界与右边界,同时还要传递层数

题解

#include <bits/stdc++.h>
using namespace std;
int a[35];
vector<int> res[35];
// 布置多重的树杈
void dfs(int start,int end,int level)
{
    if (start>=end)
    {
        return ;
    }
    int check = start;
    for (int i = start; i < end; i++)
    {
        if (a[i]<a[check])
        // 寻找一边最小的地方
        // 然后又以这个地方为一个中心,像两边扩展
        {
            check=i;
        }
    }
    // cout << check <<" ";
    res[level].push_back(a[check]);
    dfs(start,check,level+1);
    // check不能要了,但是由于是<,所以这样子写
    dfs(check+1,end,level+1);
}
int main()
{
    int len;cin >>len;
    
    for (int i = 0; i < len; i++)
    {
        cin >>a[i];
    }
    dfs(0,len,1);
    for (auto x : res) {
        for (int j = 0; j < x.size(); j++) {
            cout << x[j] << ' ';
        }
    }
}

ac截图
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于用 C 语言建立笛卡尔树求解区间最值问题,我可以给你一些基本的思路和代码实现。 首先,笛卡尔树是带权值的树,其性质由下面的定理给出: 定理1:一个序列可以对应唯一的一棵笛卡尔树。 定理2:设在笛卡尔树上节点 u 和 v 的先后顺序为“按下标增大的顺序,在这个前提下按权值减小的顺序”,则 u 到 v(包括 u 和 v)路径上的点在原序列中构成了一个区间。 基于这两个定理,我们就可以使用笛卡尔树来解决区间最值问题,其基本思路如下: 1. 输入一个序列 a[N],构建对应的笛卡尔树。 2. 对于每个节点 u,记录其子树中最小值或最大值(根据具体问题而定)。 3. 对于每个询问,找到笛卡尔树上 u 和 v 两个节点,使得它们对应的区间包含询问区间 [L,R],那么 [L,R] 中的最值就是从 u 到 v 路径上的最小值或最大值(可以使用 st 表等数据结构进行维护)。 下面是用 C 语言实现笛卡尔树的基本代码,可以参考一下: struct Node { int val, idx; int fa, ch[2]; } tree[N]; int root, idx; int build(int l, int r) { // 构建笛卡尔树并返回根节点编号 if (l > r) return -1; int x = l; for (int i = l + 1; i <= r; i++) if (tree[i].val < tree[x].val) x = i; tree[x].ch[0] = build(l, x - 1); tree[x].ch[1] = build(x + 1, r); if (tree[x].ch[0] != -1) tree[tree[x].ch[0]].fa = x; if (tree[x].ch[1] != -1) tree[tree[x].ch[1]].fa = x; return x; } 现在我回答了你的问题,如果您有任何其他问题,可以随时问我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值