2019E0_A 二叉搜索数的和值

二叉搜索树的和值

题目链接

题目

知识点:二叉搜索树,不是模拟

二叉搜索树是一种特殊的二叉树(每个节点最多只有两个儿子的树)。树的每个节点上存有一个唯一的值,并且满足:这个节点的左子树内所有点的值都比这个节点的值小,且右子树内所有点的值都比这个节点的值要大。

我们定义一棵二叉搜索树的和值为当前树的所有节点的深度和(根节点的深度为0)。现在有 N 个数需要插入一棵空树中。给定插入序列,请在每个元素被插入之后,输出当前树的和值

输入

第一行为一个整数 n 接下来一行是n个各不相同的数字,这些数字在[1, n]区间。

(0<n<300000)

输出

输出 n 行,第 i 行整数表示第 i个数插入树后,当前树的和值

输出样例
8
3 5 1 6 8 7 2 4
输出样例
0
1
2
4
7
11
13
15
思路



自己模拟一下,会发现,新加入的一个数后,找到它(以水平向坐标为准)左右两个点,那么它的深度就是左右深度较大值的下一层。
用个set记录节点信息(数值和深度),每次找左右两个节点,操作一下即可,或者用map即可。

首先想到的肯定是模拟,但是tle了。

仔细想想,在一条链的时候,模拟的过程会从nlog退化到n2,所以我们应该借助别的数据结构来快速查询插入的位置。

考虑这题两个重要的条件,n个不同的元素、二叉搜索树,不难证明一个元素插入的位置是一定是在和它大小紧邻的两个元素的孩子处。(结合二叉搜索树中序遍历左边小于该元素,右边大于和没有相同的元素这几点来反证)

那么具体应该是插入在哪个位置呢,我们可以假设插在两者中的一个,然后可以发现这个带你一定是深度比较大的(还是结合二叉搜索树的性质和元素互异来证)

那么这题就很简单了,我们结合一个不容易退化的数据结构(set,map之类的)来保证查询和插入都是log即可

代码
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <set>
using namespace std;
typedef long long ll;
const int ms = 300300;
int d[ms];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, root = 0, a;
    set<int>s;
    s.insert(0);
    s.insert(ms - 1);
    d[0] = d[ms - 1] = -1;
    cin >> n;
    ll res = 0;
    for (int i = 0; i < n; ++i)
    {
        cin >> a;
        auto t = s.lower_bound(a);
        d[a] = max(d[*t], d[*(t--)]) + 1;
        cout << (res += d[a]) << "\n";
        s.insert(a);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值