Loading [MathJax]/jax/output/HTML-CSS/jax.js

    【BZOJ】1864: [Zjoi2006]三色二叉树

    1864: [Zjoi2006]三色二叉树

    Time Limit: 1 Sec  Memory Limit: 64 MB
    Submit: 1295  Solved: 961
    [Submit][Status][Discuss]

    Description

                                                     

    Input

    仅有一行,不超过500000个字符,表示一个二叉树序列。

    Output

    输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。

    Sample Input

    1122002010

    Sample Output

    5 2

    HINT

     

    Source

    [ Submit][ Status][ Discuss]


    HOME Back

     

    其实是一道基础的树规辣~一开始觉得难点可能在建边上,可是建边也很好搞是怎么肥四??(其实就是一道水题

    建了边直接dfs往上dp就可以辣!

     

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    char s[500005];
    int now, len;
    
    int dp1[1000005][3], dp2[1000005][3], son[1000005][3];
    int MA, MI;
    
    int stot, tov[2000005], nex[2000005], h[1000005];
    
    void add ( int u, int v ) {
        tov[++stot] = v;
        nex[stot] = h[u];
        h[u] = stot;
    }
    
    void build ( int pos, int f ) {
        add ( f, pos ); add ( pos, f );
        if ( s[pos-1] == '0' ) {
            now = pos;
            return ;
        }
        if ( s[pos-1] == '1' ) {
            build ( pos + 1, pos );
        }
        if ( s[pos-1] == '2' ) {
            build ( pos + 1, pos );
            build ( now + 1, pos );
        }
    }
    
    void dfs ( int u, int f ) {
        for ( int i = h[u]; i; i = nex[i] ) {
            int v = tov[i];
            if ( v == f ) continue;
            dfs ( v, u );
            son[u][son[u][2]++] = v;
        }
        int l = son[u][0], r = son[u][1];
        if ( son[u][2] == 1 ) {
            dp1[u][0] = max ( dp1[l][1], dp1[l][2] );
            dp1[u][1] = max ( dp1[l][0], dp1[l][2] );
            dp1[u][2] = max ( dp1[l][1], dp1[l][0] ) + 1;
            dp2[u][0] = min ( dp2[l][1], dp2[l][2] );
            dp2[u][1] = min ( dp2[l][0], dp2[l][2] );
            dp2[u][2] = min ( dp2[l][1], dp2[l][0] ) + 1;
        } else if ( son[u][2] == 2 ){
            dp1[u][0] = max ( dp1[l][1] + dp1[r][2], dp1[r][1] + dp1[l][2] );
            dp1[u][1] = max ( dp1[l][0] + dp1[r][2], dp1[r][0] + dp1[l][2] );
            dp1[u][2] = max ( dp1[l][1] + dp1[r][0], dp1[r][1] + dp1[l][0] ) + 1;
            dp2[u][0] = min ( dp2[l][1] + dp2[r][2], dp2[r][1] + dp2[l][2] );
            dp2[u][1] = min ( dp2[l][0] + dp2[r][2], dp2[r][0] + dp2[l][2] );
            dp2[u][2] = min ( dp2[l][1] + dp2[r][0], dp2[r][1] + dp2[l][0] ) + 1;
        } else {
            dp1[u][0] = dp1[u][1] = 0;
            dp1[u][2] = 1;
            dp2[u][0] = dp2[u][1] = 0;
            dp2[u][2] = 1;
        }
    }
    
    int main ( ) {
        cin >> s;
        len = strlen ( s );
        build ( 1, 0 );
        dfs ( 1, 0 );
        MA = max ( dp1[1][0], max ( dp1[1][1], dp1[1][2] ) );
        MI = min ( dp2[1][0], min ( dp2[1][1], dp2[1][2] ) );
        printf ( "%d %d", MA, MI );
    }

     

    转载于:https://www.cnblogs.com/wans-caesar-02111007/p/9469533.html

    登录后您可以享受以下权益:

    ×
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值

    举报

    选择你想要举报的内容(必选)
    • 内容涉黄
    • 政治相关
    • 内容抄袭
    • 涉嫌广告
    • 内容侵权
    • 侮辱谩骂
    • 样式问题
    • 其他
    程序员都在用的中文IT技术交流社区

    程序员都在用的中文IT技术交流社区

    专业的中文 IT 技术社区,与千万技术人共成长

    专业的中文 IT 技术社区,与千万技术人共成长

    关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

    关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

    客服 返回顶部