zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    用DD-WRT自建计费WiFi热点
    docker安全最佳实践概述
    2014年8月25日,收藏家和杀手——面向对象的C++和C(一)
    Maven
    做QA的日子——iOS測试入门(四)
    小贝_mysql select连接查询
    FFmpeg源码简单分析:结构体成员管理系统-AVOption
    Keepalived+nginx+redis主从+tomcat一机多实例实现会话共享
    Redis主从配置及通过Keepalived实现Redis自动切换高可用
    CentOS 安装jdk1.7 32位
  • 原文地址:https://www.cnblogs.com/BriMon/p/9381946.html
Copyright © 2011-2022 走看看