【前言】: 今天是祖国母亲70岁生日,请允许我向祖国母亲说一声:“生日快乐!愿您永远繁荣昌盛、山清水秀!”
【题意】: 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有 n n n个房间,并且有 n − 1 n-1 n−1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。
松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去 a 1 a_1 a1,再去 a 2 a_2 a2,…,最后到 a n a_n an,去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。
维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。
因为松鼠参观指南上的最后一个房间 a n a_n an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
【思路】: 考虑到 n n n比较大( 1 ≤ n ≤ 3 × 1 0 5 1 \leq n \leq 3 \times 10^5 1≤n≤3×105),不能直接暴力,所以我们考虑用树上差分算法。
注意,我们不能对边差分,只能对点差分 ,即对于路径 ( x , y ) (x,y) (x,y)上所有点的经过次数 + 1 +1 +1,则进行以下几步( f f f为差分数组): f [ x ] + + , f [ y ] + + , f [ l c a ( x , y ) ] − − , f [ f a ( l c a ( x , y ) ) ] − − f[x]++,f[y]++,f[lca(x,y)]--,f[fa(lca(x,y))]-- f[x]++,f[y]++,f[lca(x,y)]−−,f[fa(lca(x,y))]−−
【代码】:
#include
using namespace std;
const int N=301000;
struct node{
int next,to;
}e[N<<1];int h[N],tot;
inline void add(int a,int b){
e[++tot]=(node){h[a],b};h[a]=tot;
e[++tot]=(node){h[b],a};h[b]=tot;
}//链式前向星
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
char c=0;int x=0;bool f=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}//读入优化的模板
int f[N][22],dep[N];
void dfs_init(int u,int fa){
dep[u]=dep[fa]+1;
for(int i=0;i<20;i++)
f[u][i+1]=f[f[u][i]][i];
for(int i=h[u];i;i=e[i].next){
register int v=e[i].to;
if (v==fa) continue;
f[v][0]=u;dfs_init(v,u);
}
}
inline int lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
for(int i=20;i>=0;i--)
if (dep[f[x][i]]>=dep[y]){
x=f[x][i];
}
if (x==y) return x;
for(int i=20;i>=0;i--)
if (f[x][i]!=f[y][i]){
x=f[x][i];y=f[y][i];
}
return f[x][0];
}
int dp[N];
void get_answer(int u){
for(int i=h[u];i;i=e[i].next){
register int v=e[i].to;
if (v==f[u][0]) continue;
get_answer(v);dp[u]+=dp[v];
}
}
int n,x,y,i,a[N];
int main(){
n=read();
for(i=1;i<=n;i++)
a[i]=read();
for(i=1;i<n;i++)
add(read(),read());
dfs_init(1,0);
for(i=2;i<=n;i++){
dp[a[i-1]]++;dp[a[i]]++;
dp[lca(a[i-1],a[i])]--;
dp[f[lca(a[i-1],a[i])][0]]--;
}
get_answer(1);
for(i=2;i<=n;i++)
dp[a[i]]--;//注意这里哦
for(i=1;i<n;i++)
printf("%d\n",dp[i]);
printf("%d",dp[n]);
return 0;
}