[luogu p1087] FBI树

传送门

FBI树

题目描述

我们可以把由"\(0\)"和"\(1\)"组成的字符串分为三类:全"\(0\)"串称为\(B\)串,全"\(1\)"串称为I串,既含"\(0\)"又含"\(1\)"的串则称为F串。

\(FBI\)树是一种二叉树,它的结点类型也包括\(F\)结点,\(B\)结点和I结点三种。由一个长度为\(2^N\)的"\(01\)"串S可以构造出一棵\(FBI\)\(T\),递归的构造方法如下:

  1. \(T\)的根结点为\(R\),其类型与串\(S\)的类型相同;
  2. 若串\(S\)的长度大于\(1\),将串\(S\)从中间分开,分为等长的左右子串\(S_1\)\(S_2\);由左子串\(S_1\)构造R的左子树\(T_1\),由右子串\(S_2\)构造\(R\)的右子树\(T_2\)

现在给定一个长度为\(2^N\)的"\(01\)"串,请用上述构造方法构造出一棵\(FBI\)树,并输出它的后序遍历序列。

输入输出格式

输入格式

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

第二行是一个长度为\(2^N\)的"\(01\)"串。

输出格式

一个字符串,即\(FBI\)树的后序遍历序列。

输入输出样例

输入样例 #1

3
10001011

输出样例 #1

IBFBBBFIBFIIIFF

说明

对于40%的数据,\(N \le 2\)
对于全部的数据,\(N \le 10\)
noip2004普及组第3题

分析

非常经典的一道二叉树题。根据题意建树,会发现这就是先序遍历。而题目的输出是后序遍历,那么我们就可以考虑,递归先序遍历建树,回溯的过程输出,因为先序遍历回溯就是后序遍历。

这就是大体的框架了。还有一些细节问题,比如字符串读入,和判断FBI。具体见code

代码

/*
 * @Author: crab-in-the-northeast 
 * @Date: 2020-03-08 21:40:08 
 * @Last Modified by: crab-in-the-northeast
 * @Last Modified time: 2020-03-08 23:22:06
 */
#include <iostream>
#include <cstdio>

std :: string s;

void FBI(int l, int r) {
    int mid = (l + r) >> 1;
    if(l < r) {
        FBI(l, mid);//递归建左子树
        FBI(mid + 1, r);//递归建右子树
    }
    for(int i = l + 1; i <= r; i++)
        if(s[i] != s[i - 1] && i != 1) {
            putchar('F');//如果当前和前面那个不一样,说明这个子串中既有0又有1,直接输出F,回溯。注意i = 1的情况,边界特判。
            return ;
        }
    //到这里说明子串是纯的,也就是要不然全1,要不然全0
    if(s[l] == '0') putchar('B');//全0
    else putchar('I');//全1
    return ;
}

int main() {
    int n;
    std :: cin >> n;
    std :: cin >> s;
    s = " " + s;//我喜欢让字符串初始下标是1,于是就这样了。
    FBI(1, 1 << n);
    return 0;
}

评测结果

AC 100R31542447

posted @ 2020-03-08 23:24  dbxxx  阅读(197)  评论(0编辑  收藏  举报