coderforce422e+dfs序+线段树

题意

给定一棵树!每个数有权值0||1,q个操作!

  1. get x 询问x子树为1的有多少个
  2. pow x 将x子树所有节点的值反转!!

题解

1
dfs序 将每个节点及其子树化成一段连续的区间,然后就是区间操作的线段树了!!

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

#define root 1,1,n
#define lson i<<1,L,mid
#define rson i<<1|1,mid+1,R
using namespace std;
const int N=2e5+7;
int op[N],ed[N],tree[N<<2],n;
bool lazy[N<<2];
vector<int> vec[N];
int p;
void (int x)
{
op[x]=++p;
for(auto it:vec[x])
dfs(it);
ed[x]=p;
}
void pushdown(int i,int l,int r)
{
if(lazy[i])
{
int mid=(l+r)>>1;
lazy[i]=false;
lazy[i<<1]^=1;
lazy[i<<1|1]^=1;
tree[i<<1]=(mid-l+1)-tree[i<<1];
tree[i<<1|1]=(r-mid)-tree[i<<1|1];
}
}
void pushup(int i)
{
tree[i]=tree[i<<1]+tree[i<<1|1];
}
void update(int l,int r,int i,int L,int R)
{
if(l<=L&&R<=r)
{
lazy[i]^=1;
tree[i]=(R-L+1)-tree[i];
return ;
}
int mid=(L+R)>>1;
pushdown(i,L,R);
if(l<=mid)
update(l,r,lson);
if(r>mid)
update(l,r,rson);
pushup(i);
}
int query(int l,int r,int i,int L,int R)
{
if(l<=L&&R<=r)
return tree[i];
int mid=(L+R)>>1;
pushdown(i,L,R);
int ans=0;
if(l<=mid)
ans+=query(l,r,lson);
if(r>mid)
ans+=query(l,r,rson);
return ans;
}
char com[5];
int main()
{
int a;
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
scanf("%d",&a);
vec[a].push_back(i);
}
dfs(1);
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(a) update(op[i],op[i],root);
}
int q;
scanf("%d",&q);
while(q--)
{
scanf("%s%d",com,&a);
if(com[0]=='g')
printf("%dn",query(op[a],ed[a],root));
else
update(op[a],ed[a],root);
}
return 0;
}