http://www.lydsy.com/JudgeOnline/problem.php?id=1782
给定一棵n个点的树,每次从1出发到达a[i],询问到达a[i]之后,经过了几个之前已经到达的点
简单画下图我们就能发现,每次走完就相当于给a[i]的子树权值(之后到达某个点的答案)+1,为了维护这个,我们用DFS序把子树维护到一条线段上,来回答每次询问
我们需要支持区间修改,单点查询的数据结构,很明显线段树可以,但是我想介绍一下树状数组的写法
树状数组我们知道只能单点修改,区间查询(前缀和),所以这里我们用到差分序列来维护,对于[L,R],单点修改L节点使其加一,R+1节点减一
const
maxn=100010;
var
y:array[0..maxn,1..2]of longint;
t,x,z:array[0..maxn]of longint;
w:array[0..4*maxn,1..2]of longint;
i,j,k:longint;
n,len,a,b,ans:longint;
procedure init(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0
then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;
procedure dfs(a:longint);
var tt:longint;
begin
inc(len); y[a,1]:=len; z[a]:=len;
tt:=w[a,2];
while tt<>0 do
begin
k:=y[w[tt,1],1];
if y[w[tt,1],1]=0
then dfs(w[tt,1]);
tt:=w[tt,2];
end;
y[a,2]:=len;
end;
procedure update(a,b:longint);
begin
while a<=n do
begin
inc(t[a],b);
inc(a,a and(-a));
end;
end;
function query(a:longint):longint;
var k:longint;
begin
k:=0;
while a>0 do
begin
inc(k,t[a]);
dec(a,a and(-a));
end;
exit(k);
end;
begin
readln(n); len:=n+1;
for i:=1 to n-1 do
begin
readln(a,b);
init(a,b); init(b,a);
end;
for i:=1 to n do
readln(x[i]);
len:=0;
dfs(1);
for i:=1 to n do
begin
ans:=query(z[x[i]]);
update(y[x[i],1],1); update(y[x[i],2]+1,-1);
writeln(ans);
end;
end.