P1087FBI树

题目描述

我们可以把由“ 000 ”和“ 111 ”组成的字符串分为三类:全“ 000 ”串称为 BBB 串,全“ 111 ”串称为I串,既含“ 000 ”又含“ 111 ”的串则称为F串。

FBIFBIFBI 树是一种二叉树,它的结点类型也包括 FFF 结点, BBB 结点和I结点三种。由一个长度为 2N2^N2N 的“ 010101 ”串S可以构造出一棵 FBIFBIFBI 树 TTT ,递归的构造方法如下:

1) TTT 的根结点为 RRR ,其类型与串 SSS 的类型相同;

2) 若串 SSS 的长度大于 111 ,将串 SSS 从中间分开,分为等长的左右子串 S1S_1S1​ 和 S2S_2S2​ ;由左子串 S1S_1S1​ 构造R的左子树 T1T_1T1​ ,由右子串 S2S_2S2​ 构造 RRR 的右子树 T2T_2T2​ 。

现在给定一个长度为 2N2^N2N 的“ 010101 ”串,请用上述构造方法构造出一棵 FBIFBIFBI 树,并输出它的后序遍历序列。

输入输出格式

输入格式:

 

第一行是一个整数 N(0≤N≤10)N(0 \le N \le 10)N(0≤N≤10) ,

第二行是一个长度为 2N2^N2N 的“ 010101 ”串。

 

输出格式:

 

一个字符串,即 FBIFBIFBI 树的后序遍历序列。(左右根)

 

输入输出样例

输入样例#1: 复制

3
10001011

输出样例#1: 复制

IBFBBBFIBFIIIFF

说明

对于40%的数据, N≤2N \le 2N≤2 ;

对于全部的数据, N≤10N \le 10N≤10 。

noip2004普及组第3题

 

非常普通的题,就是建立树再输出(我看了一下也有一边建树一边输出的这样会快一点,因为建的过程就是后序遍历:左右根)

顺便复习一下树:

1.建树过程中三个变量(l,r,lab),l,r不解释,lab表示在数组中位置,另外对于一个完全二叉树,它的左儿子是2*num,右儿子是2*num+1;(一种好理解方式是第n层是2^n个第n+1层是2^n个,然后第n层起点lab是2^(n-1)第n+1层为2^n)

2.另外建树时左右树是:(l,(l+r)/2,lab*2),((l+r)/2+1,r,lab*2+1)一定要加一,不然(2,3)这种情况就会陷入死循环

代码:

#include<iostream>
#include<cstdio>
#include<math.h>

using namespace std;
struct data
{
    int head,lson,rson,lab;
};
data tree[50000];
int n,num,a[50000];
int  bt(int l,int r,int num)
{
    if(l==r)
    {
        tree[num].lab=a[l];
        return 0;
    }
    bt(l,(l+r)/2,num*2);tree[num*2].head=num;
    bt((l+r)/2+1,r,num*2+1);tree[num*2+1].head=num;
    tree[num].lson=num*2; tree[num].rson=num*2+1;
    if(tree[num*2].lab==tree[num*2+1].lab)
    {
        tree[num].lab=tree[num*2].lab;
        return 0;
    } 
    tree[num].lab=2;
}
void pd(int num)
{
    if(tree[num].lab==0) printf("B");
    if(tree[num].lab==1) printf("I");
    if(tree[num].lab==2) printf("F");
}
int sc(int num)
{
    if(num>=n) pd(num);
    else
    {
        sc(num*2);sc(num*2+1);
        pd(num);
    }
}
int main()
{
    scanf("%d",&n);
    n=pow(2,n);
    for(int i=1;i<=n;i++) scanf("%1d",&a[i]);
    bt(1,n,1);
    sc(1);
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值