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
Sample Output
1
2
1
2
1
HINT
2<= n <=300000
解題思路:我把這道題作爲樹上點差分的入門題。
給你一條路,在樹上多次更新一條路徑上結點的答案。這需要用到LCA+樹上差分
由於這題涉及到點,所以是點差分。那麼我們對於每一條路徑的兩個端點u,v 我們先求出他們的LCA(u,v)=t;
那麼我們就只需要在計數數組上進行 val[u]++;val[v]++;val[t]--;val[fa[t][0]]--;
最後跑一邊DFS就夠了。
對於這題 最後把每條路的終點對答案的貢獻給去掉。(讀題讀題)
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=3e5+10;
const int DEG=20;
int n,m,head[maxn],tot,dep[maxn],fa[maxn][22],a[maxn],val[maxn],bin[21];
struct Node{
int v,next;
}node[maxn*2];
void add(int u,int v){
node[tot].v=v;node[tot].next=head[u];head[u]=tot++;
}
void init(){
mem(head,-1);tot=0;mem(val,0);
}
void bfs(int u){
queue<int> qu;
while(!qu.empty()) qu.pop();
qu.push(u);dep[u]=0;
while(!qu.empty()){
u=qu.front();qu.pop();
for(int i=1;i<DEG;i++){
if(dep[u]>=bin[i]) fa[u][i]=fa[fa[u][i-1]][i-1];
else break;
}
for(int i=head[u];~i;i=node[i].next){
int v=node[i].v;
if(v!=fa[u][0]){
dep[v]=dep[u]+1;fa[v][0]=u;
qu.push(v);
}
}
}
}
void dfs(int u){
for(int i=head[u];~i;i=node[i].next){
int v=node[i].v;
if(v!=fa[u][0]){
dfs(v);
val[u]+=val[v];
}
}
}
int LCA(int u,int v){
if(dep[u]>dep[v]) swap(u,v);
int det=dep[v]-dep[u],tu=u,tv=v;
for(int i=0;det;det>>=1,i++){
if(det&1) tv=fa[tv][i];
}
if(tv==tu) return tu;
for(int i=DEG-1;i>=0;i--){
if(fa[tu][i]==fa[tv][i]) continue;
tu=fa[tu][i];tv=fa[tv][i];
}
return fa[tu][0];
}
int main(){
int i,j,u,v;
bin[0]=1;
for(i=1;i<20;i++) bin[i]=bin[i-1]<<1;
init();
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
bfs(a[1]);
for(i=1;i<n;i++){
int l=LCA(a[i],a[i+1]);
val[a[i]]++;val[a[i+1]]++;
val[l]--;val[fa[l][0]]--;
}
dfs(a[1]);
for(i=2;i<=n;i++) val[a[i]]--;
for(j=1;j<=n;j++) printf("%d\n",val[j]);
return 0;
}