標籤:
題目大意:對樹進行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.
View Code
POJ 3321:Apple Tree(dfs序+樹狀數組)