树hash求不同子树得数量
链接:https://ac.nowcoder.com/acm/contest/2763/H
来源:牛客网
二叉查找树
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
树神精通各种树,这其中自然包括二叉查找树
立志成为小树神的cjc正在向树神学习一手二叉查找树,他问了这么一道题:将一些数顺序插入建立二叉查找树,有多少种形状不同的子树?
如果你精通数据结构,可以跳过以下内容。
二叉查找树,也称为二叉搜索树、有序二叉树或排序二叉树。它是一种具有如下性质的二叉树形结构
1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值3. 任意节点的左、右子树也分别为二叉查找树4. 没有值相等的节点。
一列数按顺序插入二叉查找树的构造方法如下
1. 若当前树为空,则加入节点,值为当前数的值,该节点视为根节点2. 若当前树不为空,则从根节点开始向下遍历。若当前数的值小于正在遍历的节点值,则向左子节点遍历,否则向右子节点遍历,直到不存在对应的子节点为止,在该处建立新的节点,值为当前数的值。
其中,树形结构在计算机学科中,一般指一种看起来像一棵倒挂的树的层次结构,如图
树形结构具有如下性质
1. 每个节点都只有有限个子节点或无子节点1.1 对于二叉树,每个节点都只有0~2个子节点2. 没有父节点的节点称为根节点3. 每一个非根节点有且只有一个父节点4. 除了根节点外,每个子节点可以分为多个不相交的子树5. 树里面没有环路
其中,子树指的是树形结构中,任意节点及其所有后代导出的子结构。二叉树左子树就是以当前节点看,它的左子节点那一分支的子树,该子树以当前节点左子节点为根。右子树就是以当前节点看,它的右子节点那一分支的子树,该子树以当前节点右子节点为根。
对于两颗二叉树子树,若忽略节点上的值,得到相同的树形结构,则认为这两颗二叉树子树形状相同。
输入描述:
第一行输入一个正整数n(1≤n≤1000)n(1\le n\le 1000)n(1≤n≤1000),代表要插入的数的个数
第二行输入n个正整数,一个1~n的排列,即1~n中每个数仅出现一次。
输出描述:
按输入顺序将数依次插入二叉查找树,输出这颗二叉查找树互不相同的子树个数。
备注:
对于样例一,建立的二叉查找树如图
不同形状的子树分别为
对于样例二,建立的二叉查找树如图
不同形状的子树分别为,
即与相同
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 const int maxn=1005; 6 int L[maxn],R[maxn]; 7 int arr[maxn]; 8 int n,tot; 9 map<pair<int,int>,int> ma; 10 11 void Find(int u,int v){ 12 if(arr[u]<arr[v]){ 13 if(R[u]==-1) R[u]=v; 14 else Find(R[u],v); 15 } 16 else{ 17 if(L[u]==-1) L[u]=v; 18 else Find(L[u],v); 19 } 20 } 21 22 int dfs(int ee){ 23 int l=-1,r=-1; 24 if(L[ee]!=-1) l=dfs(L[ee]); 25 if(R[ee]!=-1) r=dfs(R[ee]); 26 if(!ma.count({l,r})) ma[{l,r}]=++tot; 27 return ma[{l,r}]; 28 } 29 30 int main(){ 31 memset(L,-1,sizeof(L)),memset(R,-1,sizeof(R)); 32 scanf("%d",&n); 33 for(int i=1;i<=n;i++) scanf("%d",&arr[i]); 34 for(int i=2;i<=n;i++){ 35 Find(1,i); 36 } 37 dfs(1); 38 printf("%d\n",tot); 39 return 0; 40 41 }