题目描述
二叉树是一种常用的数据结构,一个二叉树或者为空,或者由根节点、左子树、右子树构成,其中左子树和右子树都是二叉树.每个节点a可以存储一个值va.
显然,如果一个点a的左子树或右子树内有一个点b,那么存在唯一的路径从a出发,每次往左子树或右子树走,经过一系列节点访问到b.我们把从a到b经过除a以外的节点数称为节点a到节点b的距离.
例如对于下图的二叉树,1为根节点,5在1的子树内,从1到5存在唯一的路径:
1->2->5,经过的除1外的节点有2个:2,5,因此节点1到节点5的距离为2.
对于一个点a,定义:
·若点b在a的左子树中,且a到b的距离为vb
,则称b为a的左关联点;
·若点b在a的右子树中,且a到b的距离为vb
,则称b为a的右关联点.
给定一个共有n个节点的二叉树,所有节点编号为1,2,...,n,其中1为根节点.给出每个节点a存储的值va,请输出每个节点的左关联点个数和右关联点个数.
显然,如果一个点a的左子树或右子树内有一个点b,那么存在唯一的路径从a出发,每次往左子树或右子树走,经过一系列节点访问到b.我们把从a到b经过除a以外的节点数称为节点a到节点b的距离.
例如对于下图的二叉树,1为根节点,5在1的子树内,从1到5存在唯一的路径:
1->2->5,经过的除1外的节点有2个:2,5,因此节点1到节点5的距离为2.

·若点b在a的左子树中,且a到b的距离为vb
,则称b为a的左关联点;
·若点b在a的右子树中,且a到b的距离为vb
,则称b为a的右关联点.
给定一个共有n个节点的二叉树,所有节点编号为1,2,...,n,其中1为根节点.给出每个节点a存储的值va,请输出每个节点的左关联点个数和右关联点个数.
输入
第一行一个正整数n,表示二叉树的总节点数.
第二行n个由空格分隔的正整数v1,v2,...,vn,第i个数vi
表示节点i存储的值.
接下来n行,第i行为两个由空格分隔的整数,分别表示编号为i的左子树的根节点(若左子树为空则为0)和右子树的根节点(若右子树为空则为0).
第二行n个由空格分隔的正整数v1,v2,...,vn,第i个数vi
表示节点i存储的值.
接下来n行,第i行为两个由空格分隔的整数,分别表示编号为i的左子树的根节点(若左子树为空则为0)和右子树的根节点(若右子树为空则为0).
输出
输出n行,第i行为两个整数,分别表示点i的左关联点个数和右关联点个数.
样例输入
5
2 1 3 2 1
2 3
4 5
0 0
0 0
0 0
提示
节点1的左关联点有2个:2和4,没有右关联点.
节点2没有左关联点,右关联点有1个:5.
除此之外,其它节点没有关联点.
对于30%的数据,n≤3.
对于60%的数据,n≤500.
对于100%的数据,n≤200000,1≤vi≤200000,根节点1到任意节点的距离不超过100000.
节点2没有左关联点,右关联点有1个:5.
除此之外,其它节点没有关联点.
对于30%的数据,n≤3.
对于60%的数据,n≤500.
对于100%的数据,n≤200000,1≤vi≤200000,根节点1到任意节点的距离不超过100000.
题解
倍增+dfs,先dfs一遍,处理出各点的父亲,再dfs时倍增找距离v[x]的父亲。

1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int N=200005; 5 struct Tree 6 { 7 int lc,rc; 8 }g[N]; 9 int n,v[N],f[N][19],fg[N][2],p[N]; 10 int read() 11 { 12 int num=0;char c;bool flag=0; 13 while((c=getchar())==' '||c=='\n'||c=='\r'); 14 if(c=='-') flag=1;else num=c-'0'; 15 while(isdigit(c=getchar())) 16 num=num*10+c-'0'; 17 return flag?-num:num; 18 } 19 void dfs1(int x) 20 { 21 if(g[x].lc) 22 f[g[x].lc][0]=x, 23 dfs1(g[x].lc); 24 if(g[x].rc) 25 f[g[x].rc][0]=x, 26 dfs1(g[x].rc); 27 } 28 int _find(int x,int vg) 29 { 30 for(int i=18;i>=0;i--) 31 if(vg>=(1<<i)&&f[x][i]) 32 vg-=(1<<i),x=f[x][i]; 33 return vg==0?x:0; 34 } 35 void dfs2(int x) 36 { 37 int fx=_find(x,v[x]); 38 fg[fx][p[fx]]++; 39 if(g[x].lc) 40 { 41 p[x]=0; 42 dfs2(g[x].lc); 43 } 44 if(g[x].rc) 45 { 46 p[x]=1; 47 dfs2(g[x].rc); 48 } 49 } 50 int main() 51 { 52 n=read(); 53 for(int i=1;i<=n;i++) 54 v[i]=read(); 55 for(int i=1;i<=n;i++) 56 g[i].lc=read(), 57 g[i].rc=read(); 58 dfs1(1); 59 for(int j=1;j<=18;j++) 60 for(int i=1;i<=n;i++) 61 f[i][j]=f[f[i][j-1]][j-1]; 62 dfs2(1); 63 for(int i=1;i<=n;i++) 64 printf("%d %d\n",fg[i][0],fg[i][1]); 65 return 0; 66 }