ZJOI2006 三色二叉树

Posted zcdhj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZJOI2006 三色二叉树相关的知识,希望对你有一定的参考价值。

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 三色二叉树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1864[ZJOI2006]三色二叉树[树形DP]

P2585 [ZJOI2006]三色二叉树

BZOJ_1864_[Zjoi2006]三色二叉树_树形DP

ZJOI2006 三色二叉树

BZOJ-1864: [Zjoi2006]三色二叉树 (julao都说简单的树形DP)

ZJOI2006 三色二叉树