码迷,mamicode.com
首页 > 其他好文 > 详细

ZJOI2006 三色二叉树

时间:2018-02-28 23:00:55      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:min   十分钟   oid   return   blog   iostream   ons   ble   string   

Luogu

orz 十分钟切掉的 M_sea 巨佬

蒟蒻用的是一种比较蠢的状态。。。

\(0\) 表示绿色

\(dp[i,color]\) 为第 \(i\) 个点被标成 \(color\) 的子树最优解。

然后转移的时候只要枚举一下儿子的颜色即可。

方程懒得写了。。。

总而言之还是 \(O(n)\) 的辣,但是常数巨大

#include <iostream>
#include <cstdio>
#include <cstring>

const int max_n = 500000 + 5;
const int inf = 0x3f3f3f3f;

int N, Tot = 1;
int Ch[2][max_n << 1], Dp1[3][max_n << 1], Dp2[3][max_n << 1];

char A[max_n];

void build(int x, int y)
{
    Ch[x][y] = ++Tot;
    if(A[Tot] == ‘0‘) return;
    if(A[Tot] == ‘1‘) build(0, Ch[x][y]);
    else
    {
        build(0, Ch[x][y]);
        build(1, Ch[x][y]);
    }
}

int main()
{
    scanf("%s", &A[1]);
    if(A[1] == ‘1‘) build(0, 1);
    else if(A[1] == ‘2‘)
    {
        build(0, 1);
        build(1, 1);
    }
    memset(Dp2, inf, sizeof(Dp2));
    for(int i = Tot; i >= 1; --i)
    {
        if(!Ch[0][i])
        {
            Dp1[0][i] = Dp2[0][i] = 1;
            Dp1[1][i] = Dp1[2][i] = Dp2[1][i] = Dp2[2][i] = 0;
            continue;
        }
        for(int j = 0; j < 3; ++j)
        {
            if(Ch[1][i] == 0)
            {
                for(int k = 0; k < 3; ++k)
                {
                    if(k != j) 
                    {
                        Dp1[j][i] = std::max(Dp1[j][i], Dp1[k][Ch[0][i]]);
                        Dp2[j][i] = std::min(Dp2[j][i], Dp2[k][Ch[0][i]]);
                    }       
                }
            }   
            else
            {
                for(int k = 0; k < 3; ++k)
                {
                    for(int l = 0; l < 3; ++l)
                    {
                        if(k != l && k != j && l != j)
                        {
                            Dp1[j][i] = std::max(Dp1[j][i], Dp1[k][Ch[0][i]] + Dp1[l][Ch[1][i]]);
                            Dp2[j][i] = std::min(Dp2[j][i], Dp2[k][Ch[0][i]] + Dp2[l][Ch[1][i]]);
                        }
                    }
                }
            }
        } 
        ++Dp1[0][i];
        ++Dp2[0][i];
    }
    printf("%d %d\n", std::max(Dp1[0][1], std::max(Dp1[1][1], Dp1[2][1])), std::min(Dp2[0][1], std::min(Dp2[1][1], Dp2[2][1])));
    return 0;
}

ZJOI2006 三色二叉树

标签:min   十分钟   oid   return   blog   iostream   ons   ble   string   

原文地址:https://www.cnblogs.com/zcdhj/p/8486010.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!