1. 程式人生 > >【HihoCoder - 1881】特殊任務 (樹形圖,遍歷)

【HihoCoder - 1881】特殊任務 (樹形圖,遍歷)

題幹:

H公司一共有N名員工,編號1~N,其中CEO是1號員工。除了CEO之外,其他員工都有唯一的直接上司,所以N名員工上下級關係恰好形成了一棵樹形結構。  

我們知道每一名員工向H公司的程式碼庫貢獻了多少行程式碼。具體來說,第i名員工貢獻了Ai行程式碼。

現在有一項特殊的任務需要2名員工完成,這兩名員工需要滿足:

1. 其中一名是另一名的直接或者間接上司

2. 兩人貢獻程式碼行數的差值越大越好

請你在所有員工中找出符合條件的2人,輸出他們程式碼行數的差值。

Input

第一行包含一個整數N。

第二行包含N個整數A1, A2, ... AN。  

以下N-1行每行包含一個整數,依次是P2, P3, ... PN,其中Pi代表第i名員工的上司編號。  

對於30%的資料,1 ≤ N ≤ 1000

對於100%的資料,1 ≤ N ≤ 100000, 0 ≤ Ai ≤ 100000, 1 ≤ Pi ≤ N

Output

一個整數代表答案

Sample Input

6
50 70 100 40 20 0  
1
1
2
4
4

Sample Output

70

解題報告:

   這題思路有如下幾種,法一:dfs序+線段樹(但是這題沒有更新所以就沒必要)。法二:直接遍歷這棵樹。其次這題沒說清楚啊n等於1是什麼鬼?不是讓選兩個人嗎?特判了一下(但是加不加那一句都可以AC,,貌似樣例中就沒有這個樣例)

簡單介紹一下變數的含義:

pair的mM分別代表最小值  最大值
tmp是所有子樹的最小值  TMP 是所有子樹的最大值
pair是單個子樹帶回的最大值最小值

AC程式碼:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
vector<int> vv[MAX];
ll a[MAX];
ll maxx;
pair<ll,ll> dfs(int cur,int root) {
	int up = vv[cur].size();
	ll tmp,TMP;
	tmp=TMP=a[cur];
	for(int i = 0; i<up; i++) {
		int v = vv[cur][i];
		if(v == root) continue;
		pair<ll,ll> mM = dfs(v,cur);
		tmp = min(tmp,mM.fi);
		TMP = max(TMP,mM.se);
		//maxx = max(maxx,max(mM.se,a[cur]) - min(mM.fi,a[cur]));
		maxx = max(maxx,abs(mM.second-a[cur]));
		maxx = max(maxx,abs(mM.first-a[cur]));
	
	}
	return pm(tmp,TMP);
}
int main()
{
	int n,m;
	cin>>n;
	for(int i = 1; i<=n; i++) scanf("%lld",a+i);
	for(int i = 2; i<=n; i++) {
		int x;
		scanf("%d",&x);
		vv[i].pb(x);vv[x].pb(i);
	}
//	if(n == 1) {
//		puts("0");return 0 ;
//	}
	pair<ll,ll> mM = dfs(1,-1);
	printf("%lld\n",maxx);
	return 0 ;
 }
 /*
5
11 10 20 3 10
1
2
1
4
 
 */

總結:

  遍歷的時候剛開始還是出錯了。。。不能直接用tmp和TMP去更新maxx,,,因為每棵子樹得分開算,並且維護一個tmp和TMP返回給父節點。。然後不能用那個註釋掉的那個maxx的更新,因為你只能用帶回來的值去和a[cur]去做運算,,不能直接在這兩者中選一個大的,兩者中選一個小的去做運算來維護maxx、、、還是要注意一下子節點(所有子樹)和單個子樹的區別吧