首页 > 其他分享 >[ZJOI2006] 三色二叉树 题解

[ZJOI2006] 三色二叉树 题解

时间:2024-07-13 11:45:06浏览次数:18  
标签:int 题解 id mx lson 二叉树 ZJOI2006 节点 build

[ZJOI2006] 三色二叉树 题解

link

趣题。

首先我们把题目分成两部分:建树和 dp 求解。

建树:观察发现,字符串中的第 \(i\) 个字符就代表图中的第 \(i\) 个节点。如果 \(S_i = 0\),直接跳过;如果 \(S_i = 1\),那么 \(i + 1\) 是 \(i\) 唯一的子节点,在两点之间连边,然后继续递归建树即可。难点在于 \(S_i = 2\) 的情况。不难发现,\(i + 1\) 仍然是 \(i\) 的一个子节点,但我们难以确定 \(i\) 的另一个子节点是什么。这时不妨先把 \(i + 1\) 的子树建完,那么建完之后字符串的下一位就是 \(i\) 的另一个子节点。为了方便,可以维护一个变量表示建树已经进行到了第几个节点(也即字符串的第几位)。

void build(int id)
{
	mx = max(mx, id);
	
	if(str[id] == '1')
	{
		G[id].push_back(id + 1), lson[id] = id + 1;
		build(id + 1);
	}
	else if(str[id] == '2')
	{
		G[id].push_back(id + 1), lson[id] = id + 1;
		build(id + 1);
		G[id].push_back(mx + 1), rson[id] = mx + 1;
		build(mx + 1); // 另一个子节点
	}
	else
	{
		/* 之后这里可以加入 dp 的初始化 */
	}
}

dp:先考虑求最大值,最小值可以类推得出。不难想到可以设 \(f(u, 0/1/2)\) 表示 \(u\) 节点分别染成 \(3\) 种颜色时, \(T(u)\) 内最多可以有多少个节点染成绿色,洛谷的题解上似乎也都是这样写的。

然而真的需要这样吗?观察发现:红色和蓝色实际上是地位相同的。注意:说它们地位相同不代表可以把它们看作一种颜色。可以这么理解:如果我有某种染色方法,把这个染色方法中的红色节点全部染成蓝色,蓝色节点全部染成红色,得到一个新的染色方法。不难发现这个新的染色方法也是合法的,并且绿色节点的个数保持不变。所以我们实际上并不需要对每个节点都设 \(3\) 种状态,\(2\) 种状态就够了。

于是,设 \(f(u, 1/0)\) 表示\(u\) 节点分别染成绿色/非绿色时, \(T(u)\) 内最多可以有多少个节点染成绿色。——这里,我们不再区分红蓝色的区别,而认为它们都是非绿色。

那么转移方程为:

\[f(u, 1) = f(lson, 0) + f(rson, 0) + 1 \\ f(u, 0) = \max(f(lson, 1) + f(rson, 0), f(lson, 0) + f(rson, 1)) \]

初始化叶子节点 \(u\) 的 \(f(u, 1) = 1\)。答案为 \(\max(f(1, 1), f(1, 0))\)。

代码:

#include<bits/stdc++.h>

using namespace std;

constexpr int MAXN = 5e5 + 10;
int n, mx, lson[MAXN], rson[MAXN], f[MAXN][2], g[MAXN][2];
char str[MAXN];
vector<int> G[MAXN];

void build(int id)
{
	mx = max(mx, id);
	
	if(str[id] == '1')
	{
		G[id].push_back(id + 1), lson[id] = id + 1;
		build(id + 1);
	}
	else if(str[id] == '2')
	{
		G[id].push_back(id + 1), lson[id] = id + 1;
		build(id + 1);
		G[id].push_back(mx + 1), rson[id] = mx + 1;
		build(mx + 1);
	}
	else
	{
		f[id][1] = 1, f[id][0] = 0;
		g[id][1] = 1, g[id][0] = 0;
	}
}

void dfs(int u)
{
	for(int v : G[u]) dfs(v);
	
	int ls = lson[u], rs = rson[u];
	f[u][1] = f[ls][0] + f[rs][0] + 1;
	f[u][0] = max({f[ls][0] + f[rs][1], f[ls][1] + f[rs][0]});
	g[u][1] = g[ls][0] + g[rs][0] + 1;
	g[u][0] = min({g[ls][0] + g[rs][1], g[ls][1] + g[rs][0]});
}

int main()
{
	cin >> (str + 1);
	
	n = strlen(str + 1);
	build(1);
	
//	for(int i = 1; i <= n; i++)
//	{
//		cerr << i << ": ";
//		if(G[i].size() == 0) cerr << "The node is a leaf node";
//		else for(auto v : G[i]) cerr << v << ' ';
//		cerr << endl;
//	}

	dfs(1);
	
	cout << max(f[1][1], f[1][0]) << ' ' << min(g[1][1], g[1][0]) << endl;
	
	return 0;
}

提交记录

标签:int,题解,id,mx,lson,二叉树,ZJOI2006,节点,build
From: https://www.cnblogs.com/dengstar/p/18299876

相关文章

  • [LeetCode]965.单值二叉树
    /*965.单值二叉树已解答简单相关标签相关企业如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回true;否则返回false。示例1:输入:[1,1,1,1,1,null,1]输出:true示例2:输入:[2,2,2,5,2]输出:false提示:给定树的节点数范围......
  • 代码随想录——监控二叉树(Leetcode968)不会
    题目链接贪心/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.val=val;}*TreeNode(intval,TreeNodeleft,Tr......
  • 2024年06月CCF-GESP编程能力等级认证C++编程三级真题解析
    本文收录于专栏《C++等级认证CCF-GESP真题解析》,专栏总目录:点这里。订阅后可阅读专栏内所有文章。一、单选题(每题2分,共30分)第1题小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级,那他可以选择的认证语言有()种。A.1B.2C.3D.4答案:C第2......
  • leetcode简单题21 N.104 二叉树的最大深度 rust描述
     //[3,9,20,null,null,15,7]3//[1,null,2]2usestd::rc::Rc;usestd::cell::RefCell;//Definitionforabinarytreenode.#[derive(Debug,PartialEq,Eq)]pubstructTreeNode{pubval:i32,publeft:Option<Rc<RefCell<TreeNode>>......
  • Codeforces Round 957 (Div. 3) A-G 题解
    CodeforcesRound957(Div.3)A-G题解A.OnlyPluses枚举思路:枚举\(a\),\(b\),\(c\)增加的次数,维护最值即可。代码:#include<bits/stdc++.h>usingnamespacestd;#definefffirst#definesssecond#definepbpush_back#defineall(u)u.begin(),u.end()#......
  • 初等数论课程测试题解
    初等数论课程测试题解刚想起来传到博客园上面。正在写。Upd.20240222:已写完,欢迎查错!一、请给出整除的概念及性质对于整数\(a,b\)\((b\neq0)\),如果存在整数\(c\),使得\(a=bc\),则称\(b\)整除\(a\),记作\(b\mida\);否则称\(b\)不整除\(a\),记作\(b\nmida\)。性质......
  • [题解] CF19D Points
    [题解]CF19DPointsCF19DPoints在一个笛卡尔坐标系中,定义三种操作:addxy:在坐标系上标记一个点\((x,y)\),保证\((x,y)\)在添加前不在坐标系上。removexy:移除点\((x,y)\),保证\((x,y)\)在移除前已在坐标系上。findxy:找到所有已标记的\((x',y')\),需满......
  • CLOI Round 2 D题题解
    一份简单的美术作业(Art)题意:给你一棵树,树上\(n\)个节点和\(n-1\)条边,每个点有一个权值,每两个黑点之间必须间隔至少一个白点,求黑点权值总和最大值,并且输出任意一种达成最大值的取点合法方案。sol:对于第一问,采用树形dp。定义\(f_{i,0/1}\)为当前节点为\(i\),当前点取或不......
  • P1262 间谍网络 题解
    题目描述给你一个有向图,可以付出代价获取一些指定的点。在获取之后要求能以获取的点为出发点,将整个图都访问到,求最小的代价。思路既然需要令总的代价最少,那么如果通过买一个点就可以访问到的所有点,自然会比买两个点的方案更优。于是自然的就可以联想到可以将图划分成很多个强......
  • [ABC328D] Take ABC 题解
    题目翻译题目描述给你一个字符串\(S\)包含A、B和C三个不用的字符。只要字符串\(S\)中包含连续的ABC就将ABC删除掉再字符串\(S\)不能操作之后输出这个字符串限制\(S\)的长度小于\(2\times10^5\)思路1总结一下这道题目的操作,可以发现就是将字符串删除一......