任務(task)


任務( \(task\) )

Description

沒頭腦是一家大公司的 \(CEO\) 。該公司由 \(N\) 人組成,編號為 \(1\)\(N\) ,沒頭腦編號為 \(1\) 。每個員工(沒頭腦除外)都有一個老板,我們說這個員工是該老板的助手。每個老板都可以有多名助手。沒頭腦沒有老板,但有他的助手。

之后會有一些任務,沒頭腦會將該任務委托給他編號最小的助手。然后,該助手也將任務委托給他編號最小的助手,並且這個過程重復進行,直到任務被發送給沒有助手的人,然后他必須親自完成任務。

執行任務的人獲得 \(1\) 個硬幣,那個人的老板獲得 \(2\) 個硬幣,老板的老板獲得 \(3\) 個硬幣,依此類推,一直到沒頭腦。之后,真正完成工作的員工意識到系統的不公平並感到傷心,並且不會再執行任務(也就是辭職)。

當公司收到的下一個任務時,因為少了一個人,所以薪水可能更少,但工作必須繼續。任務是無限多的(直到公司倒閉),因此整個過程(分配新任務,執行任務,划分薪水和執行任務人員的退出)重復進行,最后沒頭腦獨自留在公司並完成他的第一個(也是他的最后一個)任務。

當然,在此之前,沒頭腦將積累相當多的財富,但他也想知道每個員工賺了多少錢。

Input

第一行有一個整數 \(N\) ,包括沒頭腦在內的員工的個數。

第二行有 \(N-1\) 個整數,分別為 \(a_2,a_3,⋯,a_N\) ,依次表示編號 \(2,3,4,..N\) 的員工的老板。

Output

輸出一行 \(N\) 個整數,第 \(i\) 個整數表示編號為 \(i\) 的人獲得的硬幣數量。

Sample Input

【樣例1輸入】

3
1 1

【樣例2輸入】

5
1 2 2 4

Sample Output

【樣例1輸出】

5 1 1

【樣例2輸出】

13 8 1 3 1

HINT

對於 \(50 \%\) 的數據,\(2<=N<=5000\)

對於 \(100\%\) 的數據,\(2<=N<=2\times10^5\)

題目大意

給出一棵有 \(N\) 個結點的樹。從每一個葉子結點開始,它到根結點路徑上的結點貢獻依次增加 \(1\), 然后刪除遍歷到的葉子結點。重復以上過程,直到樹中的結點全部被刪除為止。(每刪除一個結點,其父親結點便會成為葉子結點)

解題思路

設每個結點的最終貢獻為 \(f_i\)

顯然,初始每個結點的貢獻都為 \(1\),即 \(f_i=1\)

假設結點 \(u\),有一子結點 \(v\),由一個葉子 \(o\) 結點到 \(v\) 的貢獻為 \(k\),則 \(o\)\(u\) 的貢獻為 \(k+1\),可得出 \(f_u=f_v+siz_v\)

由此,可得出樹上轉移方程:$$f_u=\sum\limits_{v\in son_u}f_v+siz_v$$

AC CODE

#include<bits/stdc++.h>
#define int long long
#define _ (int)3e5 + 5
using namespace std;

int n;
int head[_], to[_ << 1], nxt[_ << 1], tot;
int siz[_];
int ans[_];

void add(int a, int b)
{
	to[++tot] = b;
	nxt[tot] = head[a];
	head[a] = tot;
}

void dfs(int now)
{
	siz[now] = 1;
	ans[now] = 1;
	for(int i = head[now]; i; i = nxt[i])
	{
		int v = to[i];
		dfs(v);
		siz[now] += siz[v];
		ans[now] += ans[v] + siz[v];
	}
}

signed main()
{
	scanf("%lld", &n);
	for(int i = 2; i <= n; ++i)
	{
		int a;
		scanf("%lld", &a);
		add(a, i);
	}
	dfs(1);
	for(int i = 1; i <= n; ++i) printf("%lld ", ans[i]);
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM