把二叉树旋转先模拟几遍,要不然这个题。。。gg
模拟下叶子节点如何转为root
h:向下还能到达的深度
dep:所在的深度
lm:root到节点需要左移多少次
rm:root到节点需要右移多少次
这个方程还比较好理解,最后转为root的时候他的子树的lm,rm,一定是这样的距离
dp[root] = max(h[r[root]]+lm+1,h[l[root]]+rm+1);
关键是这部分:
lm++,dfs(l[root],max(last_max,h[r[root]]+lm+1));
lm--,rm++,dfs(r[root],max(last_max,h[l[root]]+rm+1));
rm--;
在这个节点作为root的时候比它大(之前父节点,父节点的父节点。。。。)
也会成为比它小的节点,这个就是这些节点用来更新此节点的,多模拟一下就会明白的
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
bool f[100005];//判断是否有父节点
int l[100005],r[100005];
int root;
int h[100005];//向下还能到达的深度
int dep[100005];//所在的深度
int dp[100005];
int rm,lm;
int get_num(int root,int d){
if(!root){
dep[root] = dep[root] = 0;
return 0;
}
dep[root] = d;
h[root] = max(1+get_num(l[root],d+1),1+get_num(r[root],d+1));
return h[root];
}
void dfs(int root,int last_max){
if(!root)return;
if(!f[root]){
dp[root] = 1+max(h[l[root]],h[r[root]]);
}
else{
dp[root] = max(max(h[r[root]]+lm+1,h[l[root]]+rm+1),last_max);
}
lm++,dfs(l[root],max(last_max,h[r[root]]+lm+1));
lm--,rm++,dfs(r[root],max(last_max,h[l[root]]+rm+1));
rm--;
}
int main(void){
//freopen("in.txt","r",stdin);
int n,i;
while(cin >> n && n){
rm = lm = 0;
for(i=0;i<=n;i++){
f[i] = 0;
dp[i] = 0;
}
for(i=1;i<=n;i++){
int a,b;cin >> a >> b;
//cout << a << b << endl;
l[i] = a, r[i] = b;
f[a] = f[b] = true;
}
for(i=1;i<=n;i++){
if(!f[i]){
root = i;
break;
}
}
get_num(root,1);
dfs(root,0);
for(int i=1;i<=n;i++){
printf("%d\n",dp[i]);
}
}
}