P1087 [NOIP2004 普及组] FBI 树

思路:由于递归每一层都计数[l, r]中1和0的个数复杂度太高,极限情况下,递归过程中计数的复杂度:(1024^{11} = 2^{110}),这里用前缀和记录一下1的个数,就可以每一层(O(1))复杂度获得1的个数了,做法就是根据题目说的递归构造树,然后后续遍历

空间大小问题:题目中最长序列为(2^{10}),则二叉树最多11层,则总结点数为(2^{11} - 1)

#include<iostream>
#include<string>

using namespace std;

const int N = 2500, M = 1500;

struct node{
    int l, r;
    char val;
}tr[N];

int idx;

// 2^(l - 1) = 2^N => l = N + 1

int n;
int a[M];
char s[N];

void dfs(int l, int r, int u){
    if(l == r){
        if(s[l] == '0') tr[u].val = 'B';
        else tr[u].val = 'I';
        tr[u].l = tr[u].r = -1;
        return;
    } 
    
    tr[u].l = ++ idx, tr[u].r = ++ idx;
    
    int ones = a[r] - a[l - 1];
    if(ones == r - l + 1) tr[u].val = 'I';
    else if(ones == 0) tr[u].val = 'B';
    else tr[u].val = 'F';
    
    int mid = l + r >> 1;
    dfs(l, mid, tr[u].l), dfs(mid + 1, r, tr[u].r);
}

void trav(int u){
    if(u == -1) return;
    trav(tr[u].l), trav(tr[u].r);
    cout << tr[u].val;
}

int main(){
    cin >> n;
    
    for(int i = 1; i <= 1 << n; i ++) cin >> s[i];
    for(int i = 1; i <= 1 << n; i ++)
        a[i] = a[i - 1] + (s[i] == '1');
    
    dfs(1, 1 << n, 0);
    trav(0);
    
    return 0;
}
原文地址:https://www.cnblogs.com/tomori/p/15027591.html