P1087 [NOIP2004 普及組] FBI 樹
阿新 • • 發佈:2021-07-18
思路:由於遞迴每一層都計數[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; }