思路:
对结点重编号,使得每棵子树内的结点的编号连续,便可将问题转化为树状数组求区间和,
用后序遍历对整棵树进行重编号能满足要求。
除了要在每个结点处记录新编号tag外,还要记录该结点对应的子树的最小结点编号mn,对
于每个结点x,其苹果个数为sum(x.tag)-sum(x.mn-1)。
#include
<
iostream
>
#include
<
algorithm
>
using
namespace
std;
#define
MAXN 100001
int
n,m,cnt,c[MAXN],a[MAXN];
//
cnt在结点重编号中作统计用,a[i]表示重编号后第i号结点上的苹果数
bool
s[MAXN];
struct
Link{
int
v;
Link
*
next;
}
*
link[MAXN];
struct
Node{
int
tag,mn;
}nod[MAXN];
void
init(){
memset(link,NULL,
sizeof
(link));
memset(nod,
0
,
sizeof
(nod));
memset(c,
0
,
sizeof
(c));
memset(s,
false
,
sizeof
(s));
cnt
=
1
;
Link
*
temp;
int
i,x,y;
for
(i
=
0
;i
<
n
-
1
;i
++
){
scanf(
"
%d%d
"
,
&
x,
&
y);
temp
=
new
Link;
temp
->
v
=
x;
temp
->
next
=
link[y];
link[y]
=
temp;
temp
=
new
Link;
temp
->
v
=
y;
temp
->
next
=
link[x];
link[x]
=
temp;
}
}
void
dfs(
int
u){
Link
*
temp;
nod[u].mn
=
cnt;
temp
=
link[u];
while
(temp){
if
(
!
s[temp
->
v]){
s[temp
->
v]
=
true
;
dfs(temp
->
v);
}
temp
=
temp
->
next;
}
nod[u].tag
=
cnt
++
;
}
inline
int
lowbit(
int
x){
return
x
&
(
-
x);
}
void
change(
int
x){
int
i;
if
(a[x])
for
(i
=
x;i
<
cnt;i
+=
lowbit(i))
c[i]
++
;
else
for
(i
=
x;i
<
cnt;i
+=
lowbit(i))
c[i]
--
;
}
int
sum(
int
x){
int
i,res
=
0
;
for
(i
=
x;i
>
0
;i
-=
lowbit(i))
res
+=
c[i];
return
res;
}
int
main(){
int
i,x;
char
str[
3
];
while
(scanf(
"
%d
"
,
&
n)
!=
EOF){
init();
s[
1
]
=
true
;
dfs(
1
);
scanf(
"
%d
"
,
&
m);
for
(i
=
1
;i
<
cnt;i
++
){
a[i]
=
1
;
change(i);
}
for
(i
=
0
;i
<
m;i
++
){
scanf(
"
%s
"
,str);
scanf(
"
%d
"
,
&
x);
if
(str[
0
]
==
'
Q
'
)
printf(
"
%d\n
"
,sum(nod[x].tag)
-
sum(nod[x].mn
-
1
));
else
{
a[nod[x].tag]
=
(a[nod[x].tag]
+
1
)
%
2
;
change(nod[x].tag);
}
}
}
return
0
;
}