题目描述
题解
这道题其实还是比较简单的,只需要注意heap和bst的性质:
①heap中儿子一定>=(<=)父亲。
②bst中中序遍历有序。也就是说,满足左子树<=(>=)根节点<=(>=)右子树的才是二叉排序树,仅满足左儿子<=(>=)根节点<=(>=)右儿子的树不一定是二叉排序树的。
刚开始用dfs求一下子树的最大/最小值处理起来就比较方便了。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 1005
int T,n,ty_heap,ty_bst,val[N],maxn[N],minn[N];
bool pd_heap,pd_bst;
void clear()
{
n=ty_heap=ty_bst=0; pd_heap=pd_bst=true;
memset(maxn,0,sizeof(maxn)); memset(minn,0,sizeof(minn));
}
void dfs(int now)
{
maxn[now]=minn[now]=val[now];
if ((now<<1)>n) return;
dfs(now<<1),maxn[now]=max(maxn[now],maxn[now<<1]),minn[now]=min(minn[now],minn[now<<1]);
if ((now<<1|1)<=n) dfs(now<<1|1),maxn[now]=max(maxn[now],maxn[now<<1|1]),minn[now]=min(minn[now],minn[now<<1|1]);
}
void heap(int now)
{
if ((now<<1)>n||!pd_heap) return;
if (ty_heap==-1)
{
if (minn[now<<1]<val[now]) {pd_heap=false;return;}
heap(now<<1);
if ((now<<1|1)<=n)
{
heap(now<<1|1);
if (minn[now<<1|1]<val[now]) {pd_heap=false;return;}
}
}
else
{
if (maxn[now<<1]>val[now]) {pd_heap=false;return;}
heap(now<<1);
if ((now<<1|1)<=n)
{
if (maxn[now<<1|1]>val[now]) {pd_heap=false;return;}
heap(now<<1|1);
}
}
}
void bst(int now)
{
if ((now<<1)>n||!pd_bst) return;
if (ty_bst==-1)
{
if (maxn[now<<1]>val[now]) {pd_bst=false;return;}
bst(now<<1);
if ((now<<1|1)<=n)
{
if (minn[now<<1|1]<val[now]) {pd_bst=false;return;}
bst(now<<1|1);
}
}
else
{
if (minn[now<<1]<val[now]) {pd_bst=false;return;}
bst(now<<1);
if ((now<<1|1)<=n)
{
if (maxn[now<<1|1]>val[now]) {pd_bst=false;return;}
bst(now<<1|1);
}
}
}
int main()
{
scanf("%d",&T);
for (int t=1;t<=T;++t)
{
clear();
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&val[i]);
dfs(1);
if (val[1]<val[2]||(val[1]==val[2]&&val[1]<val[3])) ty_heap=-1;else ty_heap=1;
heap(1);
if (val[2]<val[1]||(val[1]==val[2]&&val[1]<val[3])) ty_bst=-1;else ty_bst=1;
bst(1);
printf("Case #%d: ",t);
if (pd_heap&&pd_bst) puts("Both");
else if (pd_heap) puts("Heap");
else if (pd_bst) puts("BST");
else puts("Neither");
}
}