BZOJ3631 [JLOI2014]松鼠的新家

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章