题目描述
我们可以把由“ 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);
}