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
5
1 4 5 3 2
1 2
2 4
2 3
4 5
1 4 5 3 2
1 2
2 4
2 3
4 5
Sample Output
1
2
1
2
1
2
1
2
1
HINT
2<= n <=300000
树链剖分的题目在win下跑总是爆栈导致没法debug..比较怨念。只能换到lemon下加编译命令测。
这题可以先树链剖分,然后路径区间加即可了。
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct line
{
int s,t;
int next;
}a[600001];
int edge;
int head[300001];
inline void add(int s,int t)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
}
struct tree
{
int l,r;
int s;
int tag;
}tr[1200001];
inline int max(int x,int y)
{
if(x>y)
return x;
return y;
}
inline void up(int p)
{
tr[p].s=tr[p*2].s+tr[p*2+1].s;
}
inline void down(int p)
{
int l=tr[p].r-tr[p].l+1;
tr[p*2].s+=(l-l/2)*tr[p].tag;
tr[p*2+1].s+=l/2*tr[p].tag;
tr[p*2].tag+=tr[p].tag;
tr[p*2+1].tag+=tr[p].tag;
tr[p].tag=0;
}
inline void build(int p,int l,int r)
{
tr[p].l=l;
tr[p].r=r;
if(l!=r)
{
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
}
inline void change(int p,int l,int r,int x)//单点修改 l==r 故未加tag操作
{
if(l<=tr[p].l&&tr[p].r<=r)
{
tr[p].s+=(tr[p].r-tr[p].l+1)*x;
tr[p].tag+=x;
}
else
{
down(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
change(p*2,l,r,x);
if(r>mid)
change(p*2+1,l,r,x);
up(p);
}
}
inline int find(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p].s;
else
{
down(p);
int mid=(tr[p].l+tr[p].r)/2;
int ans=0;
if(l<=mid)
ans+=find(p*2,l,r);
if(r>mid)
ans+=find(p*2+1,l,r);
return ans;
}
}
int dep[300001],size[300001],son[300001],fa[300001];
int top[300001],w[300001];
int lson[300001]/*最大节点位置*/,mson[300001]/*最大节点值*/;
int tot;
inline void dfs1(int d)
{
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=fa[d])
{
dep[t]=dep[d]+1;
fa[t]=d;
dfs1(t);
son[d]+=son[t]+1;
if(son[t]>=mson[d])
{
mson[d]=son[t];
lson[d]=t;
}
}
}
}
inline void dfs2(int d)
{
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t==lson[d])
{
top[t]=top[d];
tot++;
w[t]=tot;
dfs2(t);
}
}
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=fa[d]&&t!=lson[d])
{
top[t]=t;
tot++;
w[t]=tot;
dfs2(t);
}
}
}
inline void addx(int s,int t)
{
int u=top[s],v=top[t];
while(u!=v)
{
if(dep[u]>dep[v])
{
change(1,w[u],w[s],1);
s=fa[top[s]];
}
else
{
change(1,w[v],w[t],1);
t=fa[top[t]];
}
u=top[s];
v=top[t];
}
if(w[s]<w[t])
change(1,w[s],w[t],1);
else
change(1,w[t],w[s],1);
}
int val[300001];
int main()
{
// freopen("home.in","r",stdin);
// freopen("home.out","w",stdout);
int n;
scanf("%d",&n);
int i,s,t;
for(i=1;i<=n;i++)
scanf("%d",&val[i]);
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&s,&t);
edge++;
add(s,t);
edge++;
add(t,s);
}
dep[1]=1;
dfs1(1);
top[1]=1;
tot++;
w[1]=tot;
dfs2(1);
build(1,1,n);
for(i=1;i<=n-1;i++)
{
addx(val[i],val[i+1]);
if(i!=1)
change(1,w[val[i]],w[val[i]],-1);
}
change(1,w[val[n]],w[val[n]],-1);
for(i=1;i<=n;i++)
printf("%d\n",find(1,w[i],w[i]));
return 0;
}