本题的做法是dfs序线段树。
1.什么是dfs序?
dfs从根节点遍历整棵树的过程中经过的节点编号的顺序就是dfs序。
2.如何将dfs序与线段树结合在一起?
对得到的dfs序与1-n进行映射,可以得到一个初始数组num。将dfs序中的第i个节点的标号记为x,那么num[i]表示的就是节点x上灯泡的开关情况。不难发现同一颗子树上的所有节点在dfs序中代表一个连续的区间。那么,以x为根节点子树灯泡情况的反转其实就是num数组中一段连续区间全部异或上1。那么就是一颗简单的区间修改区间查询线段树啦
下面贴上AC代码
#include<bits/stdc++.h>
#define maxn 200000 + 10
using namespace std;
struct node {
int sum;
int lazy;
}tree[maxn << 2];
int pos[maxn], npos[maxn], cnt;
int st[maxn],num[maxn];
int n, tmp;
vector<int>e[maxn];
void dfs(int x)
{
num[x] = 1;
pos[x] = ++cnt; npos[cnt] = x;
for (int i = 0; i < e[x].size(); i++) {
dfs(e[x][i]);
num[x] += num[e[x][i]];
}
}
void build(int x, int L, int R)
{
if (L == R) {
tree[x].sum = st[npos[L]];
return;
}
int mid = L + R >> 1;
build(x << 1, L, mid);
build(x << 1 | 1, mid + 1, R);
tree[x].sum = tree[x << 1].sum + tree[x << 1 | 1].sum;
}
void update(int cur, int L, int R)
{
int mid = L + R >> 1;
tree[cur << 1].sum = mid - L + 1 - tree[cur << 1].sum;
tree[cur << 1 | 1].sum = R - mid - tree[cur << 1 | 1].sum;
tree[cur << 1].lazy ^= 1;
tree[cur << 1 | 1].lazy ^= 1;
tree[cur].lazy = 0;
}
int query(int cur, int L, int R, int x, int y)
{
if (x == L&&y == R) return tree[cur].sum;
int mid = L + R >> 1;
if (tree[cur].lazy) update(cur, L, R);
if (mid >= y)return query(cur << 1, L, mid, x, y);
else if (mid + 1 <= x)return query(cur << 1 | 1, mid + 1, R, x, y);
else return query(cur << 1, L, mid, x, mid) + query(cur << 1 | 1, mid + 1, R, mid + 1, y);
}
void modify(int cur, int L, int R, int x, int y)
{
if (L == x&&R == y) {
tree[cur].sum = y - x + 1 - tree[cur].sum;
tree[cur].lazy ^= 1;
return;
}
int mid = L + R >> 1;
if (tree[cur].lazy)update(cur, L, R);
if (mid >= y)modify(cur << 1, L, mid, x, y);
else if (mid + 1 <= x)modify(cur << 1 | 1, mid + 1, R, x, y);
else modify(cur << 1, L, mid, x, mid), modify(cur << 1 | 1, mid + 1, R, mid + 1, y);
tree[cur].sum = tree[cur << 1].sum + tree[cur << 1 | 1].sum;
}
int main()
{
int n; scanf("%d", &n);
for (int i = 2; i <= n; i++) {
scanf("%d", &tmp);
e[tmp].push_back(i);
}
for (int i = 1; i <= n; i++)scanf("%d", &st[i]);
dfs(1);
build(1, 1, n);
int q; scanf("%d", &q);
char ord[15];
int p;
while (q--) {
scanf("%s%d", ord, &p);
if (ord[0] == 'g')printf("%d\n", query(1, 1, n, pos[p], pos[p] + num[p] - 1));
else modify(1, 1, n, pos[p], pos[p] + num[p] - 1);
}
}