题意
所有房间成一棵有根树,房间1为根节点,每一次pow操作要求把当前节点在内的,以及他的子树全部反转一遍即1变成0,0变成1。每一次get操作进行求和,算出该节点在内的和他子树所有房间为1的个数即求和。
方法:dfs序建线段树,用模板进行修改一下即可。区间反转问题还是一样,要对该区间操作为奇数才进行反转偶数次操作无效,也就对应了lazy标记该怎么推。先初始化线段树然后每一次如果是有效操作,那么sum变成(区间长度-sum)即翻转一次。针对一颗一般的树,我们如果要进行区间修改,一般都有dfs序进行转化成线段树,即求出每一个节点他的子树的开始编号和结束编号,这样因为每一次我们深度优先就可以保证更新区间是连续的。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
char ch = getchar(); int x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e5 + 10;
int n,q;
int st[N], ed[N];
int sum[N << 2], lazy[N << 2];
struct {
int to, next;
}edge[N];
int head[N];
int cnt = 0;
int num = 0;
void addedge(int fr, int to)
{
edge[cnt].to = to;
edge[cnt].next = head[fr];
head[fr] = cnt++;
}
void dfs(int u)
{
st[u] = ++num;
for (int i = head[u]; ~i; i = edge[i].next)
{
dfs(edge[i].to);
}
ed[u] = num;
}
void pushup(int root)
{
sum[root] = sum[lrt] + sum[rrt];
}
void pushdown(int root, int l, int r)
{
int len = (r - l + 1);
int lenl = len - (len >> 1); int lenr = (len) >> 1;
if (lazy[root] % 2)
{
lazy[lrt] += lazy[root];
lazy[rrt] += lazy[root];
sum[lrt] = lenl - sum[lrt];
sum[rrt] = lenr - sum[rrt];
lazy[root] = 0;
}
}
void build(int l, int r, int root)
{
lazy[root] = 0;
if (l == r) { sum[root] = 0; return; }
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(root);
}
void init(int l, int r, int root, int pos, int val)
{
if (l == r) { sum[root] = val; return; }
int mid = (l + r) >> 1;
if (pos <= mid)init(lson, pos, val);
else init(rson, pos, val);
pushup(root);
}
void update(int l, int r, int root, int lf, int rt)
{
if (lf <= l && r <= rt)
{
sum[root] = (r - l + 1) - sum[root];
lazy[root]++;
return;
}
pushdown(root, l, r);
int mid = (l + r) >> 1;
if (lf <= mid)update(lson, lf, rt);
if (rt > mid)update(rson, lf, rt);
pushup(root);
}
int querry(int l, int r, int root, int lf, int rt)
{
if (lf <= l && r <= rt)return sum[root];
pushdown(root, l, r);
int mid = (l + r) >> 1;
int ans = 0;
if (lf <= mid)ans += querry(lson, lf, rt);
if (rt > mid)ans += querry(rson, lf, rt);
return ans;
}
int main()
{
memset(head, -1, sizeof(head));
n = read(); int x;
upd(i,2, n)
{
x = read(); addedge(x, i);
}
build(1, n, 1);
dfs(1);
up(i, 0, n)
{
x = read();
init(1, n, 1, st[i + 1], x);
}
q = read();
char s[20];
while (q--)
{
scanf("%s", s);
if (s[0] == 'g')
{
x = read();
cout << querry(1, n, 1, st[x], ed[x]) << endl;
}
else
{
x = read();
update(1, n, 1, st[x], ed[x]);
}
}
return 0;
}