适用组别:提高组
难度系数:7
P5854
笛卡尔树是这样的一棵二叉树:首先,它是一个最小堆,即除了根结点,每个节点的权值都大于父节点的权值;其次,它的中序遍历恰好就是给定的序列。 笛卡尔树也可以是最大堆,逻辑相应改变。
笛卡尔树是一棵二叉树,树的每个节点有两个值,一个为key,一个为value。光看key的话,笛卡尔树是一棵二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大;光看value的话,笛卡尔树有点类似堆,根节点的value是最小的,每个节点的value都比它的子树要小。
例题:
下图就是一棵对应的笛卡尔树。现输入序列的规模n(1≤n<100) 和序列的 n 个元素,试求其对应的笛卡尔树的深度 d(根节点深度为 1),以及有多少个叶子节点的深度为 d。
实例序列:
7 2 12 1 10 5 15 3
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /**************************************************************** * Description: C++ implementation of Cartesian tree 笛卡尔树 * Author: Alex Li * Date: 2023-07-06 13:02:29 * LastEditTime: 2023-07-06 13:11:50 ****************************************************************/ #include <iostream> using namespace std; const int SIZE=100; const int INFINITY=100000; int n,a[SIZE], maxDeep,num; void Solve(int left, int right, int deep){ int i,j,min; if(deep>maxDeep){ maxDeep=deep; num=1; } else if(deep==maxDeep)num++; min=INFINITY; for ( i =left; i <=right; i++) if(min>a[i]){ min=a[i]; j=i; } if(left<j)Solve(left,j-1,deep+1); if(j<right)Solve(j+1,right,deep+1); } int main(){ cin>>n; for (int i =1; i <=n; i++) cin>>a[i]; maxDeep=0; Solve(1,n,1); cout<<maxDeep<<' '<<num<<endl; } /* intput: 8 7 2 12 1 10 5 15 3 output: 4 2 */ |
I4585