[vijos1897]学姐吃牛排(dfs+heap+bst)

72 篇文章 0 订阅
14 篇文章 0 订阅

题目描述

传送门

题解

这道题其实还是比较简单的,只需要注意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");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值