题目地址
题意:给你一棵树,1为根节点,每个节点都有应该状态0或者1,你有两种操作,pow的操作是把该节点以及他的所有子树的每个节点进行自身异或的操作,get就是查询该节点以及他的所有子树的每个节点有多少个1。
思路:我们先通过dfs一边把所有的子树搜索出来,并标记好,然后我们通过这个给出的子树的范围对线段树进行更新,之后的操作就是根据之前求出的子树范围来更新和查询,线段树就是一个简单的区间更新+延迟更新。
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 200010
#define LL __int64
#define inf 0x3f3f3f3f
#define lson l,mid,ans<<1
#define rson mid+1,r,ans<<1|1
#define getMid (l+r)>>1
#define movel ans<<1
#define mover ans<<1|1
using namespace std;
const LL mod = 1e9 + 7;
const double eps = 1e-9;
struct node {
LL sum;
int lazy;
int l, r;
}sum[N << 2];//线段树主体
int num[N], pos[N], len[N], pre[N], cnt;
vector<int> v[N];
struct Segment__Tree {
int x, y;
void pushUp(int ans) {
sum[ans].sum = sum[movel].sum + sum[mover].sum;
}
void pushDown(int ans) {
if (sum[ans].lazy) {
sum[movel].lazy ^= 1;
sum[mover].lazy ^= 1;
sum[movel].sum = sum[movel].r - sum[movel].l + 1 - sum[movel].sum;
sum[mover].sum = sum[mover].r - sum[mover].l + 1 - sum[mover].sum;
sum[ans].lazy = 0;
}
}
void build(int l, int r, int ans) {
sum[ans].l = l;
sum[ans].r = r;
sum[ans].lazy = 0;
if (l == r) {
sum[ans].sum = num[pre[l]];
return;
}
int mid = getMid;
build(lson);
build(rson);
pushUp(ans);
}
LL solve(int l, int r, int ans) {
if (l >= x&&r <= y) {
return sum[ans].sum;
}
pushDown(ans);
int mid = getMid;
if (mid<x) {
return solve(rson);
}
else if (mid >= y) {
return solve(lson);
}
else {
return solve(lson) + solve(rson);
}
}
void updata(int l, int r, int ans) {
if (l >= x&&r <= y) {
sum[ans].sum = r - l + 1 - sum[ans].sum;
sum[ans].lazy ^= 1;
return;
}
pushDown(ans);
int mid = getMid;
if (mid<x) {
updata(rson);
}
else if (mid >= y) {
updata(lson);
}
else {
updata(lson);
updata(rson);
}
pushUp(ans);
}
}tree;
void init(int n) {
for (int i = 0; i <= n; i++) {
v[i].clear();
}
}
void dfs(int u) {
int lens = v[u].size();
for (int i = 0; i < lens; i++) {
int vv = v[u][i];
pos[vv] = ++cnt;//子树的起点
pre[cnt] = vv;
dfs(vv);
len[vv] = cnt;//子树的终点
}
}
int main() {
cin.sync_with_stdio(false);
int n, x, q;
string str;
while (cin >> n) {
init(n);
for (int i = 2; i <= n; i++) {
cin >> x;
v[x].push_back(i);
}
for (int i = 1; i <= n; i++) {
cin >> num[i];
}
cin >> q;
cnt = 0;
pos[1] = ++cnt;
pre[cnt] = 1;
len[1] = n;
dfs(1);
tree.build(1, n, 1);
while (q--) {
cin >> str;
if (str[0] == 'g') {
cin >> x;
tree.x = pos[x];
tree.y = len[x];
cout << tree.solve(1, n, 1) << endl;
}
else {
cin >> x;
tree.x = pos[x];
tree.y = len[x];
tree.updata(1, n, 1);
}
}
}
return 0;
}