• [BZOJ1864][Zjoi2006]三色二叉树


    Description

    Input

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

    Output

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

    Sample Input

    1122002010

    Sample Output

    5 2


    仔细考虑我们发现,一个节点的颜色只有是绿色和不是绿色两种。

    如果一个点x不是绿色,那么根据抽屉原理,它的两个儿子一定是一个绿色,一个不是绿色。

    如果这个点是绿色,那么它的两个儿子一定都不是绿色,然后又回到了上面那一条。

    归纳得证。

    所以我们设f[x][0/1]为x节点不是绿色/是绿色,它的子树的最多的绿色点的个数。

    显然f[x][1] = f[ls[x]][0] + f[rs[x]][0] + 1;

    f[x][0] = max(f[ls[x][0] + f[rs[x]][1], f[rs[x][0] + f[ls[x]][1]).

    最小值同理。

    这题的读入比较有意思...递归读入...


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm> 
    using namespace std;
    
    int ls[500005], rs[500005], cnt;
    
    void in(int x)
    {
        int y ;
        scanf("%1d", &y);
        if (y == 1) in(ls[x]=++cnt);
        else if (y == 2)in(ls[x]=++cnt), in(rs[x]=++cnt);
    }
    
    int f[500005][2];//1:绿色,0:不是绿色 
    int g[500005][2];
    
    void dfs(int x)
    {
        if (ls[x]) dfs(ls[x]);
        if (rs[x]) dfs(rs[x]);
        f[x][1] = max(f[x][1], f[ls[x]][0] + f[rs[x]][0] + 1);
        f[x][0] = max(f[x][0], max(f[ls[x]][1] + f[rs[x]][0], f[rs[x]][1] + f[ls[x]][0]));
    }
    
    void efs(int x)
    {
        if (ls[x]) efs(ls[x]);
        if (rs[x]) efs(rs[x]);
        g[x][1] = g[ls[x]][0] + g[rs[x]][0] + 1;
        g[x][0] = min(g[ls[x]][1] + g[rs[x]][0], g[rs[x]][1] + g[ls[x]][0]);    
    }
    
    int main()
    {
        in(++cnt);
        dfs(1);
        efs(1);
        printf("%d %d
    ", max(f[1][1], f[1][0]), min(g[1][1], g[1][0]));
        return 0;
    }
  • 相关阅读:
    酷睿i3/i5/i7到底有啥区别,该怎么选
    酷睿i3/i5/i7到底有啥区别,该怎么选
    感谢AMD,是它我们才用得上Intel的超性价比的智能处理器
    如何在ASP.NET2.0中通过Gmail发送邮件
    Asp.Net事务和异常处理:
    080414 雨
    080415 晴
    还有四天
    助けて
    今晚安排
  • 原文地址:https://www.cnblogs.com/BriMon/p/9381946.html
Copyright © 2020-2023  润新知