感觉非常巧妙的一题。。
如果对于一个已经建立完成的树, 那么我们可以用dp[ i ]表示染完 i 这棵子树, 并给从fa[ i ] -> i的条边也染色的最少颜色数。
mnson[ i ][ 0 ] 和 mnson[ i ][ 1 ]分别表示 i 的儿子的dp值的最大和第二大的值, 那么dp[ i ] = max(mnson[ i ][ 0 ], mnson[ i ][ 1 ] + 1)
根据树链剖分的原理我们知道dp的最大值不超过log(n), 那么每次加入一个新的点, 我们暴力地往上更新dp值, 直到当前的dp值不变。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1000000007; const double eps = 1e-6; const double PI = acos(-1); int n, fa[N], mxson[N][2], dp[N]; int main() { scanf("%d", &n); for(int i = 2; i <= n + 1; i++) scanf("%d", &fa[i]); for(int i = 2; i <= n + 1; i++) { int u = i; while(1) { if(u == 1 || dp[u] >= max(mxson[u][0], mxson[u][1] + 1)) break; dp[u] = max(mxson[u][0], mxson[u][1] + 1); if(dp[u] >= mxson[fa[u]][0]) { mxson[fa[u]][1] = mxson[fa[u]][0]; mxson[fa[u]][0] = dp[u]; } else if(dp[u] > mxson[fa[u]][1]) { mxson[fa[u]][1] = dp[u]; } u = fa[u]; } printf("%d ", mxson[1][0]); } puts(""); return 0; } /* */