题目大意:对树进行m次操作,有两类操作,一种是改变一个点的权值(将0变为1,1变为0),另一种为查询以x为根节点的子树点权值之和,开始时所有点权值为1。
分析:
对树进行dfs,将树变为序列,记录每个点进栈出栈的时间戳作为其对应区间的左右端点,那么其子节点对应区间必在该区间内,对这段区间求和即可,用树状数组进行修改与求和。
代码:
program apple; type point=^node; node=record x:longint; next:point; end; var a:array[0..100000]of point; bit:array[0..200000]of longint; b,v1,v2:array[0..100000]of longint; g:array[0..100000]of boolean; n,i,m,d,x,y:longint; c:char; procedure add(x,y:longint); var p:point; begin new(p); p^.x:=y; p^.next:=a[x]; a[x]:=p; end; procedure dfs(x:longint); var p:point; begin inc(d); v1[x]:=d; g[x]:=true; new(p); p:=a[x]; while p<>nil do begin if g[p^.x]=false then dfs(p^.x); p:=p^.next; end; inc(d); v2[x]:=d; end; procedure change(x:longint); var i,y:longint; begin y:=x; if b[x]=0 then i:=1 else i:=-1; x:=v1[x]; while (x<=2*n) do begin inc(bit[x],i); inc(x,x and (-x));end; b[y]:=1-b[y]; end; function query(x:longint):longint; var s:longint; begin s:=0; while x>0 do begin inc(s,bit[x]); dec(x,x and (-x)); end; exit(s); end; begin readln(n); for i:=1 to n-1 do begin readln(x,y); add(x,y); add(y,x); end; d:=0; dfs(1); for i:=1 to n do change(i); readln(m); for i:=1 to m do begin readln(c,x); if c=‘C‘ then change(x) else writeln(query(v2[x])-query(v1[x]-1)); end; end.
时间: 2024-10-14 12:39:01