BZOJ - 2654 ZJOI 三色二叉树 DFS序 树形DP

大家都很强, 可与之共勉 。

1864: [Zjoi2006]三色二叉树

Time Limit: 1 Sec Memory Limit: 64 MB
Description

Input

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

Output

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

Sample Input

1122002010

Sample Output

5 2

HINT

Source

Day1

用f[i]表示点i是绿色时最多有多少个点能被染成绿色,g[i]表示i不是绿色时最多有多少个点被染成绿色,容易推出状态转移方程:
f[i]=g[ch[i][0]]+g[ch[i][1]]+1;
g[i]=max(f[ch[i][0]]+g[ch[i][1]],f[ch[i][1]]+g[ch[i][0]]);
最小值把max换成min即可。

/**************************************************************
    Problem: 1864
    User: Lazer2001
    Language: C++
    Result: Accepted
    Time:24 ms
    Memory:11076 kb
****************************************************************/

# include 

inline int max ( int a, int b )  {  return a > b ? a : b ;  }
inline int min ( int a, int b )  {  return a < b ? a : b ;  }

const int N = 500005 ;

int f [N], g [N] ;
int st [N], top ;
int son [N] [2] ;
int n ;
char s [N], ch ;

int main ( )  {
    while ( ( ch = getchar ( ) ) == ' ' || ( ch == '\n' ) || ( ch == '\t') || ( ch == '\r' ) ) ;
    for ( s [n ++] = ch ; ( ch = getchar ( ) ) != '\n' && ( ch != '\t' ) && ( ch != '\r' ) && ( ch ^ -1 ) ; s [n ++] = ch ) ;
    for ( int i = 1 ; i <= n ; ++ i )  {
        if ( son [st [top]] [0] )  son [st [top --]] [1] = i ;
        else son [st [top --]] [0] = i ;
        for ( int j = 0 ; j < s [i - 1] - 48 ; ++ j )    st [++ top] = i ;
    }
    for ( int i = n ; i ; -- i )  {
        f [i] = g [son [i] [0]] + g [son [i] [1]] + 1 ;
        g [i] = max ( f [son [i] [0]] + g [son [i] [1]], f [son [i] [1]] + g [son [i] [0]] ) ;
    }

    printf ( "%d ", max ( f [1], g [1] ) ) ;

    for ( int i = n ; i ; -- i )  {
        f [i] = g [son [i] [0]] + g [son [i] [1]] + 1 ;
        g [i] = min ( f [son [i] [0]] + g [son [i] [1]], f [son [i] [1]] + g [son [i] [0]] ) ;
    }

    printf ( "%d\n", min ( f [1], g [1] ) ) ;
}

你可能感兴趣的:(树形DP,BZOJ)