[P2585] [ZJOI2006]三色二叉树(树形dp)

【原题】

一棵二叉树可以按照如下规则表示成一个由 0、1、2 组成的字符序列,我们称之为“二叉树序列 \(S\)”:

\(S = \begin{cases}0,表示该树没有子节点\\ 1S_1,表示该树有一个节点,S_1为其子树的二叉树序列\\ 2S_1S_2,表示该树由两个子节点,S_1和S_2分别表示其两个子树的二叉树序列\end{cases}\)

例如,下图所表示的二叉树可以用二叉树序列 \(S = 21200110\) 来表示。

haha.png

你的任务是要对一棵二叉树的节点进行染色。每个节点可以被染成红色、绿色或蓝色。并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不同。给定一颗二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色。

输入格式

输入只有一行一个字符串 \(s\),表示二叉树序列。

输出格式

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

输入输出样例

输入 #1

1122002010

输出 #1

5 2

说明/提示

数据规模与约定

对于全部的测试点,保证\(1≤∣s∣≤5×10^5\)\(s\) 中只含字符 0 1 2

【思路】

树形dp简单题

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '\n'
#define lson  rt << 1
#define rson  rt << 1 | 1
#define f(x, y, z) for (int LL x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int maxn = 5e5 + 7;
const int mod = 1e9 + 7;

int n, m;
string s;
int p = 0, cnt = 1;
int f[maxn * 4][3], g[maxn  * 4][3];

struct node
{
	int l, r, cnt;
}nd[maxn * 4];

int build(int nw, int pos)
{
	if (s[pos] == '0') nd[nw].l = nd[nw].r = -1;
	else if (s[pos] == '1')
	{
		p++;
		nd[nw].l = ++cnt;
		build(cnt, p);
		nd[nw].r = -1;
	}
	else
	{
		p++;
		nd[nw].l = ++cnt;
		build(cnt, p);
		p++;
		nd[nw].r = ++cnt;
		build(cnt, p);
	}
	return 0;
}

int col(int nw)
{
	if (nd[nw].l == -1 && nd[nw].r == -1)
	{
		f[nw][0] = g[nw][0] = 1;
		return 0;
	}
	else if(nd[nw].r == -1)
	{
		int v = nd[nw].l;
		col(v);
		f[nw][0] = max(f[v][1], f[v][2]) + 1;
		f[nw][1] = max(f[v][0], f[v][2]);
		f[nw][2] = max(f[v][0], f[v][1]);
		g[nw][0] = min(g[v][1], g[v][2]) + 1;
		g[nw][1] = min(g[v][0], g[v][2]);
		g[nw][2] = min(g[v][0], g[v][1]);
		return 0;
	}
	else
	{
		int l = nd[nw].l, r = nd[nw].r;
		col(l);
		col(r);
		f[nw][0] = max(f[l][1] + f[r][2], f[l][2] + f[r][1]) + 1;
		f[nw][1] = max(f[l][0] + f[r][2], f[l][2] + f[r][0]);
		f[nw][2] = max(f[l][0] + f[r][1], f[l][1] + f[r][0]);
		g[nw][0] = min(g[l][1] + g[r][2], g[l][2] + g[r][1]) + 1;
		g[nw][1] = min(g[l][0] + g[r][2], g[l][2] + g[r][0]);
		g[nw][2] = min(g[l][0] + g[r][1], g[l][1] + g[r][0]);
		return 0;
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> s;
	build(1, 0);
	col(1);
	cout << max(f[1][0], max(f[1][1], f[1][2])) << " " << min(g[1][0], min(g[1][1], g[1][2]))<< endl;
}
posted @ 2020-09-03 22:09  kurum!  阅读(182)  评论(0编辑  收藏  举报