P2585 三色二叉树 题解
题目
一棵二叉树可以按照如下规则表示成一个由0、1、2组成的字符序列,我们称之为"二叉树序列S":
\begin{aligned}
0 &\ \ 表示该树没有子节点 \\
1S_1 &\ \ 表示该树有一个子节点,S_1为其子树的二叉树序列 \\
2S_1S_2 &\ \ 表示该树有两个子节点,S_1和S_2分别表示其两个子树的二叉树序列
\end{aligned}
\right.
\]
例如,下图所表示的二叉树可以用二叉树序列S=21200110来表示:

你的任务是要对一棵二叉树的节点进行染色。每个节点可以被染成红色、绿色或蓝色。并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不相同。给定一棵二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色
输入格式
输入文件仅有一行,不超过\(5\times 10^5\)个字符,表示一个二叉树序列
输出格式
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色
输入样例
1122002010
输出样例
5 2
题解
直接用输入DFS来树形DP.
定义maxv和minv两个数组,maxv[i][j]表示以\(i\)号节点为根节点的子树最多能染成绿色的节点数量,当\(j=0\),根节点被染成绿色;当\(j=1\),根节点被染成红色;当\(j=2\),根节点被染成蓝色.
minv类似,代表最少能染成绿色的节点数量.
当根节点有一个子节点时,这个子节点不能和根节点一个颜色,所以从剩下的两种颜色中挑选最大的更新.注意当根节点为绿色时,dp值需要加1(多了根节点一个绿色节点)
当根节点有两个子节点时,这两个子节点不能和根节点一个颜色,而又只剩下两种颜色,所以有两种情况,从这两种情况中选最大的更新即可.同样注意当根节点为绿色时的情况.
那么,怎么DFS这一个特殊序列?
首先可以确定的是,根节点就是第一项,那么通过第一项可以得知根节点有几个子树,如果这棵树不为空,那么左子树的根节点一定是第二项,注意如果只有一棵子树,那么我把唯一的一棵子树看作左子树.
再对左子树进行相同的递归操作,遇到0回溯,因为保证叶节点一定为0,所以不需要检查边界,回溯的时候,可以返回这棵子树在序列中最后一项的位置,这个位置加一就是右子树(如果有两棵子树).
以此类推,就能在不建树的情况下DFS它
代码
#include <iostream>
#include <string>
using namespace std;
const int maxn = 10005;
string s;
int maxv[maxn][3], minv[maxn][3];
int dfs(int root) {
if (s[root] == '0') {
maxv[root][0] = minv[root][0] = 1; // 因为叶节点没有子树,所以若该叶节点不为绿色,这棵子树中绿色节点的个数为0,反之为1
return root; // 这棵子树的结尾坐标
}
int lend = dfs(root + 1); // 递归左子树
if (s[root] == '1') {
maxv[root][0] = max(maxv[root+1][1],maxv[root+1][2])+1; // 这个是绿色的,需要额外算上根节点
maxv[root][1] = max(maxv[root+1][0],maxv[root+1][2]); // 这两种代表什么颜色其实无关紧要
maxv[root][2] = max(maxv[root+1][0],maxv[root+1][1]);
minv[root][0] = min(minv[root+1][1],minv[root+1][2])+1;
minv[root][1] = min(minv[root+1][0],minv[root+1][2]);
minv[root][2] = min(minv[root+1][0],minv[root+1][1]);
return lend; // 如果有一棵子树,左子树的结尾就是这棵子树的结尾
} else {
int rend = dfs(lend + 1); // 根据左子树的结尾递归右子树
maxv[root][0] = max(maxv[root+1][1]+maxv[lend+1][2],maxv[root+1][2]+maxv[lend+1][1])+1;
maxv[root][1] = max(maxv[root+1][0]+maxv[lend+1][2],maxv[root+1][2]+maxv[lend+1][0]);
maxv[root][2] = max(maxv[root+1][0]+maxv[lend+1][1],maxv[root+1][1]+maxv[lend+1][0]);
minv[root][0] = min(minv[root+1][1]+minv[lend+1][2],minv[root+1][2]+minv[lend+1][1])+1;
minv[root][1] = min(minv[root+1][0]+minv[lend+1][2],minv[root+1][2]+minv[lend+1][0]);
minv[root][2] = min(minv[root+1][0]+minv[lend+1][1],minv[root+1][1]+minv[lend+1][0]);
return rend; // 如果有两棵子树,右子树的结尾才是这棵子树的结尾
}
}
int main() {
cin >> s;
dfs(0);
// 三种情况选最大/最小
cout<<max(maxv[0][0], max(maxv[0][1], maxv[0][2]))<<" "<<min(minv[0][0], min(minv[0][1], minv[0][2]))<<endl;
return 0;
}
P.S.
最近记忆力有点下降,这道题在两个网站上的数据范围不同,我照着第一个写,交到第二个上面,疯狂RE,死盯了半个小时也没找到原因...
P2585 三色二叉树 题解的更多相关文章
- luogu P2585 [ZJOI2006]三色二叉树
P2585 [ZJOI2006]三色二叉树 题目描述 输入输出格式 输入格式: 输入文件名:TRO.IN 输入文件仅有一行,不超过10000个字符,表示一个二叉树序列. 输出格式: 输出文件名:TRO ...
- 【树形DP】洛谷P2585 [ZJOI2006] 三色二叉树
[树形DP]三色二叉树 标签(空格分隔): 树形DP [题目] 一棵二叉树可以按照如下规则表示成一个由0.1.2组成的字符序列,我们称之为"二叉树序列S": 0 该树没有子节点 1 ...
- 【BZOJ1864】[Zjoi2006]三色二叉树 树形DP
1864: [Zjoi2006]三色二叉树 Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最 ...
- 【BZOJ1864】三色二叉树(动态规划)
[BZOJ1864]三色二叉树(动态规划) 题面 BZOJ 题解 首先把树给构出来. 设\(f[i][0/1]\)表示当前节点\(i\),是否是绿色节点的子树中最大/最小的绿色节点的个数和. 转移很显 ...
- 嘴巴题5 「BZOJ1864」[ZJOI2006] 三色二叉树
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 1195 Solved: 882 [Submit][Status ...
- BZOJ1864[ZJOI2006]三色二叉树[树形DP]
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 773 Solved: 548[Submit][Status] ...
- 【BZOJ-1864】三色二叉树 树形DP
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 659 Solved: 469[Submit][Status] ...
- BZOJ 1864: [Zjoi2006]三色二叉树( 树形dp )
难得的ZJOI水题...DFS一遍就行了... ----------------------------------------------------------------------- #inc ...
- BZOJ_1864_[Zjoi2006]三色二叉树_树形DP
BZOJ_1864_[Zjoi2006]三色二叉树_树形DP 题意: 分析:递归建树,然后DP,从子节点转移. 注意到红色和蓝色没有区别,因为我们可以将红蓝互换而方案是相同的.这样的话我们只需要知道当 ...
随机推荐
- DirectX11 With Windows SDK--31 阴影映射
前言 阴影既暗示着光源相对于观察者的位置关系,也从侧面传达了场景中各物体之间的相对位置.本章将起底最基础的阴影映射算法,而像复杂如级联阴影映射这样的技术,也是在阴影映射的基础上发展而来的. 学习目标: ...
- 提高网站访问性能之Tomcat优化
一.前言 tomcat 服务器在JavaEE项目中使用率非常高,所以在生产环境对tomcat的优化也变得非常重要了,对于tomcat的优化,主要是从2个方面入手,一是tomcat本身的配置,另一个是t ...
- 2.Redis 控制短信重发
需要两个缓存 key名称 phone-busy,缓存1分钟key名称 phone-send-count,缓存1天,每成功发送一条+1 发送的时候流程如下: 判断phone-busy是否存在,存在直接报 ...
- easypoi 读取 Excel 简单应用
背景 在做接口测试的时候,经常会使用 Excel 来存储对应的接口信息和用例信息,为了方便程序的读取,引入easypoi 工具来读取 Excel 内容.easypoi 比起 poi 使用更加的方便,代 ...
- git添加所有新文件
git add -A 提交所有变化 git add -u 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new) git add . 提交新文件(new)和被修改(mod ...
- GestureDetector手势检测
Android手势检测器GestureDetector,要创建一个GestureDetector需要传入一个监听器GestureDetector.OnGestureListener. 案例(实现手机相 ...
- Python学习日志-02
(2)Python如何运行程序 Python解释器简介: Python不仅仅是一门编程语言,它也是一个名为解释器的软件包.解释器是一种让其他程序运行起来的程序.当你编写了一段Python程序,Pyth ...
- 解除git文件处于lock状态方法
解决办法: 去git文件夹下删除lock文件就可以
- Jmeter Response Data 乱码问题解决方法
1. 进入jmeter\apache-jmeter-4.0\bin,打开jmeter.properties 2. 搜索“sampleresult.default.encoding” 设置sampler ...
- Project Loom:Reactive模型和协程进行时(翻译)
Java 15将发布Project Loom的第一个版本.我相信这将改变JVM.在这篇文章中,我想深入探讨一下导致我相信这一点的原因. 首先,我们需要了解核心问题.然后,我将尝试描述以前的技术如何解决 ...