题目大意
一个有n个节点的树,树的每个节点可能有一个苹果或没有,有两种操作:
C x 将节点x的权值改变,即如果有一个苹果删掉,否则增加一个苹果。
Q x 询问以节点x为根的子树中有多少个苹果。
数据范围:1 <= n <= 100000, 询问个数m <= 100000
分析
对于棵树进行dfs遍历,并记录每一个点的dfs序号(st[i]),在一个节点的所有儿子都被遍历过后,记录当前en[i]为当前最大dfs序号的节点的dfs序号(en[i])。
将问题转化为了区间操作
C x 将某一点的权值改变
Q x 询问区间[st[x],en[x]]的和
树状数组和线段树可以轻松实现这些操作。
代码
type
pnode=^tnode;
tnode=record
lc,rc:pnode;
c:longint;
end;
var
t:pnode;
i,j,k:longint;
x,y:longint;
n,m:longint;
co:longint;
s:char;
a:array[0..110000,0..1000] of longint;
b:array[1..110000,1..3] of longint;
procedure make(r,l:longint);
var
i,j,k:longint;
begin
for i:=1 to a[r,0] do
if a[r,i]=l then break;
if a[r,i]=l
then
begin
j:=i;
a[r,0]:=a[r,0]-1;
for i:=j to a[r,0] do
a[r,i]:=a[r,i+1];
end;
for i:=1 to a[r,0] do
make(a[r,i],r);
end;
procedure dfs(r:longint;var nm:longint);
var
i,j,k:longint;
begin
b[r][1]:=nm;
for i:=1 to a[r,0] do
begin
nm:=nm+1;
dfs(a[r,i],nm);
end;
b[r][2]:=nm;
end;
procedure neww(var t:pnode);
begin
if t=nil then
begin
new(t);
t^.c:=0;
t^.lc:=nil;
t^.rc:=nil;
end;
end;
procedure insert(var t:pnode; l,r,x,y:longint; var iif:longint);
var
i,j,k:longint;
mid:longint;
begin
with t^ do
begin
{if c=0 then
begin }
mid:=(l+r) div 2;
if (l=x) and (r=y)
then
begin
if c=0
then
begin
c:=1;
iif:=1;
end
else
begin
c:=0;
iif:=-1;
end;
exit;
end;
if (l<=x) and (mid>=y)
then
begin
neww(lc);
insert(lc,l,mid,x,y,iif);
c:=c+iif;
exit;
end;
if (mid<x) and (r>=y)
then
begin
neww(rc);
insert(rc,mid+1,r,x,y,iif);
c:=c+iif;
exit;
end;
neww(lc);
neww(rc);
insert(lc,l,mid,x,mid,iif);
c:=c+iif;
iif:=0;
insert(rc,mid+1,r,mid+1,y,iif);
c:=c+iif;
end;
{end;}
end;
procedure insert1(var t:pnode; l,r:longint);
var
i,j,k:longint;
mid:longint;
begin
with t^ do
begin
{if c=0 then
begin }
mid:=(l+r) div 2;
if l=r
then
begin
c:=1;
exit;
end;
neww(lc);
neww(rc);
insert1(lc,l,mid);
c:=c+lc^.c;
insert1(rc,mid+1,r);
c:=c+rc^.c;
end;
{end;}
end;
function find(t:pnode;l,r,x,y:longint):longint;
var
mid:longint;
begin
if t=nil then exit(0);
with t^ do
begin
mid:=(l+r) div 2;
if (l=x) and (r=y)
then
begin
find:=c;
exit;
end;
if (l<=x) and (mid>=y)
then
begin
find:=find(lc,l,mid,x,y);
exit;
end;
if (mid<x) and (r>=y)
then
begin
find:=find(rc,mid+1,r,x,y);
exit;
end;
find:=find(lc,l,mid,x,mid)+find(rc,mid+1,r,mid+1,y);
end;
end;
begin
readln(m);
for x:=1 to m-1 do
begin
readln(i,j);
a[i,0]:=a[i,0]+1;
a[i,a[i,0]]:=j;
a[j,0]:=a[j,0]+1;
a[j,a[j,0]]:=i;
end;
make(1,0);
i:=1;
dfs(1,i);
readln(n);
fillchar(t,sizeof(t),0);
j:=0;
neww(t);
insert1(t,1,m);
for i:=1 to n do
begin
readln(s,x);
j:=0;
if s='C' then insert(t,1,m,b[x][1],b[x][1],j)
else writeln(find(t,1,m,b[x][1],b[x][2]));
end;
end.