P2585 tricolor binary solution to a problem

topic

May represent a binary tree in accordance with the following rules into a sequence of characters consisting of 0,1,2, which we call "binary sequence S":

\ [S = \ left \ {\ begin {aligned} 0 & \ \ represents a node of the tree has no children \\ 1S_1 & \ \ represents the tree has a child node, the binary tree sequence S_1 its subtree \\ 2S_1S_2 & \ \ represents the tree has two child nodes, S_1 and S_2 represent two binary sequences of their sub-tree \ end {aligned} \ right. \]

For example, the binary tree may be represented by FIG binary sequence S=21200110is represented:

Your task is to stain the nodes of a binary tree. Each node can be colored red, green or blue. Further, the color of a node and its child node must be different, if the node has two child nodes, then the color of the two child nodes must be different. A binary sequence of a given binary tree, the tree request the most and the least number of points to be colored green

Input Format

The only line of input file, no more than \ (5 \ times 10 ^ 5 \) characters represent a binary sequence

Output Format

The output file is only one line contains two numbers, respectively for the most and least number of points can be dyed green

SAMPLE INPUT

1122002010

Sample Output

5 2

answer

DFS to directly input tree DP.

Definitions maxvand minvtwo arrays, maxv[i][j]represented by \ (I \) No. subtree root node up to the number of green dyed nodes, when \ (J = 0 \) , the root is stained green; if \ (J 1 = \) , the root is stained red; when \ (J = 2 \) , the root node were stained blue.

minvSimilarly, green represents the minimum number of nodes can be dyed.

When the root node has a child node, the child nodes of the root node and not a color, so pick the biggest update from the remaining two colors. When the root note is green, dp values ​​need to add 1 (multi-root a green node node)

When the root node has two children, and two sub-root node can not a color, but only two colors, so there are two cases, two cases selected from the largest update to. Also note that when root for the case when green.

So, how DFS that a special sequence?

First, be sure that the first item is the root node, then the first item that may have several sub-tree root node, if the tree is not empty, then left the child must be the root of the tree a second term, attention If only a sub-tree, then I put only a sub-tree seen as a left sub-tree.

And then the left subtree same recursive operation encountered 0 back as to ensure a certain leaf node is 0, so no need to check the border, back when you can return to the sub-tree tree position in the sequence of the last one, this position plus one is the right subtree (if there are two sub-tree).

So, it will be able to DFS without achievements

Code

#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.

Recent memory decline somewhat different on this question at two sites range data, shining my first writing, submitted to a second top, crazy RE, Siding half an hour did not find a reason ...

Guess you like

Origin www.cnblogs.com/youxam/p/P2585.html