[BZOJ3631] [JLOI2014] 松鼠的新家


傳送門

http://www.lydsy.com/JudgeOnline/problem.php?id=3631

題目大意

給定一棵無根樹和一個序列,在這個序列上依次遍歷,求每個點的訪問次數(最后一個點的訪問次數要-1)

題解

樹剖

const
maxn=300010;
var
w:array[0..3*maxn,1..2]of longint;
bite,fa,son,size,dep,top,pos,x:array[0..maxn]of longint;
i,j,k:longint;
n,m,len,a,b:longint;
procedure swap(var a,b:longint);
var c:longint;
begin c:=a; a:=b; b:=c; end;

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 dfs1(a:longint);
var tt,v:longint;
begin
tt:=w[a,2]; size[a]:=1; v:=0;
while tt<>0 do
begin
if w[tt,1]<>fa[a]
then
begin
fa[w[tt,1]]:=a; dep[w[tt,1]]:=dep[a]+1;
dfs1(w[tt,1]);
inc(size[a],size[w[tt,1]]); if size[w[tt,1]]>size[v] then v:=w[tt,1];
end;
tt:=w[tt,2];
end;
son[a]:=v;
end;

procedure dfs2(a,pre:longint);
var tt:longint;
begin
tt:=w[a,2]; inc(len); pos[a]:=len; top[a]:=pre;
if son[a]<>0 then dfs2(son[a],pre);
while tt<>0 do
begin
if (w[tt,1]<>fa[a])and(w[tt,1]<>son[a]) then dfs2(w[tt,1],w[tt,1]);
tt:=w[tt,2];
end;
end;

procedure update(a,b:longint);
begin
while a<=n+1 do
begin
inc(bite[a],b);
inc(a,a and (-a));
end;
end;

function query(a:longint):longint;
var ans:longint;
begin
ans:=0;
while a>0 do
begin
inc(ans,bite[a]);
dec(a,a and (-a));
end;
exit(ans);
end;

procedure change(a,b:longint);
begin
update(pos[b],-1); update(pos[b]+1,1);
while top[a]<>top[b] do
begin
if dep[top[a]]<dep[top[b]] then swap(a,b);
update(pos[top[a]],1); update(pos[a]+1,-1);
a:=fa[top[a]];
end;
if dep[a]>dep[b] then swap(a,b);
update(pos[a],1); update(pos[b]+1,-1);
end;

begin
readln(n); len:=n+1;
for i:=1 to n do
read(x[i]);
for i:=1 to n-1 do
begin readln(a,b); init(a,b); init(b,a); end;
fa[1]:=0; dep[1]:=1; size[0]:=0;
dfs1(1);
len:=0;
dfs2(1,1);
for i:=1 to n-1 do
change(x[i],x[i+1]);
for i:=1 to n do
writeln(query(pos[i]));
end.

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com