题目描述
小杨有⼀棵包含 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]);
}
}
结果
