[BZOJ1782] [Usaco2010 Feb]slowdown 慢慢游

来源:互联网 发布:福建医科大学网络教育 编辑:程序博客网 时间:2024/05/17 17:38

传送门

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.
0 0
原创粉丝点击