zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    CSU1784
    HDU 6128 Inverse of sum(数学)
    容斥原理入门
    HDU 6129 Just do it(规律)
    HDU 6140 Hybrid Crystals(zz)
    HDU 6143 Killer Names(排列+容斥,dp)
    zzuli 2177 Contest
    zzuli 2180 GJJ的日常之沉迷数学(逆元)
    除法逆元入门
    乘法逆元数论篇
  • 原文地址:https://www.cnblogs.com/tomori/p/15027591.html
Copyright © 2011-2022 走看看