cogs2840. 二叉查找树

二叉查找树

 

 

时间限制:1 s   内存限制:512 MB

【题目描述】

 

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

对于一棵二叉查找树T,我们可以将一个值为 x的新点插入 T中,且保持树的性质。算法如下:

需要将 x 插入树 T时,执行 insert(x,T.root)。

 

现在有 N 个数需要插入一棵空树中。给定插入序列,请在每个元素被插入之后,输出所有节点的深度总和(根的深度为 0)。

【输入格式】

 

输入的第一行一个整数 n,表示序列长度。

 

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

【输出格式】

 

 

输出 n 行,第 i 行整数表示第 i个数插入树后,至这个节点的节点深度总和。

 

 

【样例输入】

8
3 5 1 6 8 7 2 4

【样例输出】

0
1
2
4
7
11
13
15

【数据规模与约定】

 

对于 50%的数据,满足n ≤ 1000

对于100%的数据,满足n ≤ 3 ∗ 1e5

 

【来源】

qbxt 2017.10.7 t1

 

 

我们可以发现,这棵二叉搜索树构建完毕之后,根节点总是比他的子树内任意一个节点先插入 ,而直接构造是n^2级别的,我们需要知道有一种东西叫笛卡尔树,其实就是一颗treap,既满足二叉搜索树的性质,又满足堆的性质,对于任意一个节点有两个值,key和fix,key满足二叉搜索树,fix满足堆,如果key是按大小顺序插入的,那么我们可以在O(n)的时间内构造出这棵树,那么我们就按题目中所给数字大小顺序插入,fix值为其插入时间,就可以构造出符合题目的那棵树了。(key和fix给定时可以唯一确定一棵树)

 1 #include<cstdio>
 2 #define ll long long
 3 using namespace std;
 4 const int inf=3e5+10;
 5 int fix[inf],n,fa[inf],dep[inf],a[inf];
 6 ll ans;
 7 int main()
 8 {
 9     scanf("%d",&n);
10     for(int i=1;i<=n;i++){
11         scanf("%d",&a[i]);
12         fix[a[i]]=i;
13     }
14     for(int i=1;i<=n;i++){
15         int last=0,f=i-1;
16         while(fix[f]>fix[i])last=f,f=fa[f];
17         fa[i]=f;
18         fa[last]=i;
19     }
20     dep[0]=-1;
21     for(int i=1;i<=n;i++){
22         dep[a[i]]=dep[fa[a[i]]]+1;
23         ans+=dep[a[i]];
24         printf("%lld\n",ans);
25     }
26     return 0;
27 }
View Code

 

转载于:https://www.cnblogs.com/hyghb/p/8228287.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值