Description
松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
Input
第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。
Output
一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。
Sample Input
1
4
5
3
2
1 2
2 4
2 3
4 5
Sample Output
2
1
2
1
HINT
30%的数据,n<=4000
80%的数据,n<=50000
100%的数据,2<= n <=300000
Source
#include<stdio.h>
int a[300001];
int f[300001][21];
int level[300001];
int ans[300001][50];
int queue[300001];
int to[600001];
int next[600001];//边开2倍,双向边
int head[300001];
int fa[300001];
int sum,tmp;
void addedge(int a,int b)//链表加边
{
next[++sum]=head[a];
head[a]=sum;
to[sum]=b;
}
void dfs(int x)
{
for(int i=1;i<=18;i++)
{
if(level[x]>=(1<<i))
f[x][i]=f[f[x][i-1]][i-1];
else
break;
}
for(int i=head[x];i;i=next[i])
{
if(to[i]==f[x][0])
continue;
level[to[i]]=level[x]+1;
f[to[i]][0]=x;
dfs(to[i]);
}
}
int lca(int a,int b)
{
if(level[a]<level[b])
tmp=a,a=b,b=tmp;
int deep=level[a]-level[b];
/*if(a==b)
return a;*/
for(int i=0;i<19;i++)
{
if((deep&(1<<i))!=0)
a=f[a][i];
}
/*if(a==b)
return a;*/
for(int j=18;j>=0;j--)
{
if(f[a][j]!=f[b][j])
a=f[a][j],b=f[b][j];
}
if(a==b)
return a;//和上面一样.
return f[a][0];
}
void dfs2(int x)
{
for(int j=head[x];j;j=next[j])//注意,j=next[x];
{
if(to[j]==f[x][0])
continue;
dfs2(to[j]);
fa[x]+=fa[to[j]];
}
}
int main()
{
int n,c,b;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&c,&b);
addedge(c,b);
addedge(b,c);
}
dfs(a[1]);//以1为树根寻找
for(int i=1;i<n;i++)
{
int father=lca(a[i],a[i+1]);
//printf("%d\n",father);
fa[a[i]]++,fa[a[i+1]]++;
fa[father]--;
fa[f[father][0]]--;//差分数组修改
}
dfs2(a[1]);
for(int i=2;i<=n;i++)
fa[a[i]]--;
for(int i=1;i<=n;i++)
printf("%d\n",fa[i]);
}