洛谷P1087 FBI樹

若把你比作歌發表於2024-05-27

洛谷P1087

遞迴建立樹,根據當前樹的型別,選擇“F”“B”“I”

void build(int depth, int start, int end, int root){
    if (depth >= n+1) return;
    int current = root;
    int flag = check(start, end);
    if (flag == 0) t[current].self = 'B';
    else if (flag == 1) t[current].self = 'I';
    else t[current].self = 'F';

    t[current].left = ++cnt;
    build(depth + 1, start, (start + end) / 2, cnt);

    t[current].right = ++cnt;
    build(depth + 1, (start + end) / 2 + 1, end, cnt);
}
t[current].left = ++cnt;
build(depth + 1, (start + end) / 2 + 1, end, cnt);
t[current].right = ++cnt;
build(depth + 1, start, (start + end) / 2, cnt);

這一部分保證了子節點不會被重複指向
遞迴建立因為每一次建立,cnt都會加1,所以不會重複指向

AC程式碼

#include<bits/stdc++.h>
using namespace std;
int n, cnt = 1;
vector<int> num;

struct node{
    char self;
    int left, right;
    node(): left(0), right(0), self('*'){}
};
vector<node> t;

int check (int start, int end) {
    int flag0 = 0, flag1 = 0;
    for (int i = start; i <= end; i++) {
        if (num[i] == 0) flag0 = 1;
        if (num[i] == 1) flag1 = 1;
    }
    if (flag0 == 0 && flag1 == 1) return 1;
    if (flag0 == 1 && flag1 == 0) return 0;
    return 2;
}

void build(int depth, int start, int end, int root){
    if (depth >= n+1) return;
    int current = root;
    int flag = check(start, end);
    if (flag == 0) t[current].self = 'B';
    else if (flag == 1) t[current].self = 'I';
    else t[current].self = 'F';

    t[current].left = ++cnt;
    build(depth + 1, start, (start + end) / 2, cnt);

    t[current].right = ++cnt;
    build(depth + 1, (start + end) / 2 + 1, end, cnt);
}

void print(int root) {
    if (t[root].self == '*') return;
    print(t[root].left);
    print(t[root].right);
    cout << t[root].self;
}

int main() {
    cin >> n;
    num.resize((1<<(n+1))+100);
    t.resize((1<<(n+2))+100);
    char ch;
    for (int i = 1; i <= (1<<n); i++) {
        cin >> ch;
        num[i] = ch-'0';
    }
    build(0, 1, (1<<n), 1);
    print(1);
}

相關文章