bzoj1864 三色二叉树

Description

Input

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

Output

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

Sample Input

1122002010

Sample Output

5 2
树形dp
int mx[N][3][3]; //点i的颜色为0/1/2,点i为根的子树最多有多少个0/1/2
int mn[N][3][3]; //点i的颜色为0/1/2,点i为根的子树最少有多少个0/1/2
然后各种乱搞
(写的太挫辣。。。直接meta-programming是可以解决的。。。)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <cmath>
#include <cctype>
#include <string>
#include <cfloat>
#include <stack>
#include <cassert>
#include <bitset>

using namespace std;

const int N = 500010;

char str[N];

int ch[N][2], cnt, pos;

int build() {
    if(str[pos] == 0) return 0;
    ++ cnt;
    int cur = cnt;
    int tmp = cnt;
    if(str[pos] == '0') {
        pos ++;
    } else if(str[pos] == '1') {
        pos ++;
        ch[cur][0] = build();
    } else {
        pos ++;
        ch[cur][0] = build();
        ch[cur][1] = build();
    }
    return cur;
}

int mx[N][3][3];   //点i的颜色为0/1/2,点i为根的子树最多有多少个0/1/2

int mn[N][3][3];   //点i的颜色为0/1/2,点i为根的子树最少有多少个0/1/2

void dfs(int u) {
    int c1 = ch[u][0], c2 = ch[u][1];
    if(c1 && c2) {
        //有两个儿子
        dfs(c1);
        dfs(c2);

        mx[u][0][0] = max(mx[c1][1][0] + mx[c2][2][0], mx[c1][2][0] + mx[c2][1][0]) + 1;
        mx[u][0][1] = max(mx[c1][1][1] + mx[c2][2][1], mx[c1][2][1] + mx[c2][1][1]);
        mx[u][0][2] = max(mx[c1][1][2] + mx[c2][2][2], mx[c1][2][2] + mx[c2][1][2]);
        mx[u][1][0] = max(mx[c1][0][0] + mx[c2][2][0], mx[c1][2][0] + mx[c2][0][0]);
        mx[u][1][1] = max(mx[c1][0][1] + mx[c2][2][1], mx[c1][2][1] + mx[c2][0][1]) + 1;
        mx[u][1][2] = max(mx[c1][0][2] + mx[c2][2][2], mx[c1][2][2] + mx[c2][0][2]);
        mx[u][2][0] = max(mx[c1][0][0] + mx[c2][1][0], mx[c1][1][0] + mx[c2][0][0]);
        mx[u][2][1] = max(mx[c1][0][1] + mx[c2][1][1], mx[c1][1][1] + mx[c2][0][1]);
        mx[u][2][2] = max(mx[c1][0][2] + mx[c2][1][2], mx[c1][1][2] + mx[c2][0][2]) + 1;

        mn[u][0][0] = min(mn[c1][1][0] + mn[c2][2][0], mn[c1][2][0] + mn[c2][1][0]) + 1;
        mn[u][0][1] = min(mn[c1][1][1] + mn[c2][2][1], mn[c1][2][1] + mn[c2][1][1]);
        mn[u][0][2] = min(mn[c1][1][2] + mn[c2][2][2], mn[c1][2][2] + mn[c2][1][2]);
        mn[u][1][0] = min(mn[c1][0][0] + mn[c2][2][0], mn[c1][2][0] + mn[c2][0][0]);
        mn[u][1][1] = min(mn[c1][0][1] + mn[c2][2][1], mn[c1][2][1] + mn[c2][0][1]) + 1;
        mn[u][1][2] = min(mn[c1][0][2] + mn[c2][2][2], mn[c1][2][2] + mn[c2][0][2]);
        mn[u][2][0] = min(mn[c1][0][0] + mn[c2][1][0], mn[c1][1][0] + mn[c2][0][0]);
        mn[u][2][1] = min(mn[c1][0][1] + mn[c2][1][1], mn[c1][1][1] + mn[c2][0][1]);
        mn[u][2][2] = min(mn[c1][0][2] + mn[c2][1][2], mn[c1][1][2] + mn[c2][0][2]) + 1;
    } else if(c1) {
        //有一个儿子
        dfs(c1);

        mx[u][0][0] = max(mx[c1][1][0], mx[c1][2][0]) + 1;
        mx[u][0][1] = max(mx[c1][1][1], mx[c1][2][1]);
        mx[u][0][2] = max(mx[c1][1][2], mx[c1][2][2]);
        mx[u][1][0] = max(mx[c1][0][0], mx[c1][2][0]);
        mx[u][1][1] = max(mx[c1][0][1], mx[c1][2][1]) + 1;
        mx[u][1][2] = max(mx[c1][0][2], mx[c1][2][2]);
        mx[u][2][0] = max(mx[c1][0][0], mx[c1][1][0]);
        mx[u][2][1] = max(mx[c1][0][1], mx[c1][1][1]);
        mx[u][2][2] = max(mx[c1][0][2], mx[c1][1][2]) + 1;

        mn[u][0][0] = min(mn[c1][1][0], mn[c1][2][0]) + 1;
        mn[u][0][1] = min(mn[c1][1][1], mn[c1][2][1]);
        mn[u][0][2] = min(mn[c1][1][2], mn[c1][2][2]);
        mn[u][1][0] = min(mn[c1][0][0], mn[c1][2][0]);
        mn[u][1][1] = min(mn[c1][0][1], mn[c1][2][1]) + 1;
        mn[u][1][2] = min(mn[c1][0][2], mn[c1][2][2]);
        mn[u][2][0] = min(mn[c1][0][0], mn[c1][1][0]);
        mn[u][2][1] = min(mn[c1][0][1], mn[c1][1][1]);
        mn[u][2][2] = min(mn[c1][0][2], mn[c1][1][2]) + 1;
    } else {
        //没有儿子
        mx[u][0][0] = 1;
        mx[u][0][1] = 0;
        mx[u][0][2] = 0;
        mx[u][1][0] = 0;
        mx[u][1][1] = 1;
        mx[u][1][2] = 0;
        mx[u][2][0] = 0;
        mx[u][2][1] = 0;
        mx[u][2][2] = 1;

        mn[u][0][0] = 1;
        mn[u][0][1] = 0;
        mn[u][0][2] = 0;
        mn[u][1][0] = 0;
        mn[u][1][1] = 1;
        mn[u][1][2] = 0;
        mn[u][2][0] = 0;
        mn[u][2][1] = 0;
        mn[u][2][2] = 1;
    }
}

int main() {
    scanf("%s", str);
    build();
    dfs(1);
    printf("%d %d\n", 
        max(mx[1][0][0], max(mx[1][1][0], mx[1][2][0])),
        min(mn[1][0][0], min(mn[1][1][0], mn[1][2][0])));
}

  

posted @ 2017-09-11 23:18  KingSann  阅读(211)  评论(0编辑  收藏  举报