关联点


题目描述

二叉树是一种常用的数据结构,一个二叉树或者为空,或者由根节点、左子树、右子树构成,其中左子树和右子树都是二叉树.每个节点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,请输出每个节点的左关联点个数和右关联点个数.

输入

第一行一个正整数n,表示二叉树的总节点数.
第二行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

样例输出 

2 0
0 1
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.

题解

倍增+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 }
View Code

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM