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])));
}


浙公网安备 33010602011771号