洛谷 P10722 [GESP202406 六级] 二叉树-普及/提高-

题目描述

小杨有⼀棵包含 nnn 个节点的二叉树,且根节点的编号为 111。这棵二叉树任意⼀个节点要么是白色,要么是黑色。之后小杨会对这棵二叉树进行 qqq 次操作,每次小杨会选择⼀个节点,将以这个节点为根的子树内所有节点的颜色反转,即黑色变成白色,白色变成黑色。

小杨想知道 qqq 次操作全部完成之后每个节点的颜色。

输入格式

第⼀行一个正整数 nnn,表示二叉树的节点数量。

第二行 (n−1)(n-1)(n−1) 个正整数,第 iii(1≤i≤n−11\le i\le n-11≤i≤n−1)个数表示编号为 (i+1)(i+1)(i+1) 的节点的父亲节点编号,数据保证是⼀棵二叉树。

第三行一个长度为 nnn 的 01\texttt{01}01 串,从左到右第 iii(1≤i≤n1\le i\le n1≤i≤n)位如果为 0\texttt{0}0,表示编号为 iii 的节点颜色为白色,否则为黑色。

第四行⼀个正整数 qqq,表示操作次数。

接下来 qqq 行每行⼀个正整数 aia_iai(1≤ai≤n1\le a_i\le n1≤ai≤n),表示第 iii 次操作选择的节点编号。

输出格式

输出一行一个长度为 nnn 的 01\texttt{01}01 串,表示 qqq 次操作全部完成之后每个节点的颜色。从左到右第 iii(1≤i≤n1\le i\le n1≤i≤n) 位如果为 0\texttt{0}0,表示编号为 iii 的节点颜色为白色,否则为黑色。

输入输出样例 #1

输入 #1

复制代码
6
3 1 1 3 4
100101
3
1
3
2

输出 #1

复制代码
010000

说明/提示

样例解释

第一次操作后,节点颜色为:011010\texttt{011010}011010

第二次操作后,节点颜色为:000000\texttt{000000}000000

第三次操作后,节点颜色为:010000\texttt{010000}010000

数据范围
子任务编号 得分 nnn qqq 特殊条件
111 202020 ≤105\le 10^5≤105 ≤105\le 10^5≤105 对于所有 i≥2i\ge 2i≥2,节点 iii 的父亲节点编号为 i−1i-1i−1
222 404040 ≤1000\le 1000≤1000 ≤1000\le 1000≤1000
333 404040 ≤105\le 10^5≤105 ≤105\le 10^5≤105

对于全部数据,保证有 n,q≤105n,q\le 10^5n,q≤105。

solution

可以用欧拉序,子树上的所有节点的 dfn 序一定在根节点的两次访问顺序之间

代码

cpp 复制代码
#include <iostream>
#include "bit"
#include "vector"
#include "unordered_set"
#include "set"
#include "queue"
#include "algorithm"
#include "bitset"

using namespace std;

const int N = 1e5 + 2;

int n, m, x, dfn[N], dfm[N], id;
vector<int> son[N];
bool col[N], c[N];

void dfs(int u) {
    dfn[u] = ++id;
    for (int v: son[u]) {
        dfs(v);
    }
    dfm[u] = id;
}

int main() {
    cin >> n;
    for (int i = 2; i <= n; i++) {
        cin >> x;
        son[x].push_back(i);
    }

    dfs(1);

    for (int i = 1; i <= n; i++) {
        char y; cin >> y;
        x = y - '0';
        col[i] = x;
    }


    cin >> m;
    for (int i = 0; i < m; i++) {
        cin >> x;
        c[dfm[x] + 1] ^= 1;
        c[dfn[x]] ^= 1;
    }

    for (int i = 1; i <= n; i++) {
        c[i] ^= c[i - 1];
    }

    for (int i = 1; i <= n; i++) {
        cout << (c[dfn[i]] ^ col[i]);
    }
}

结果