關聯點


題目描述

二叉樹是一種常用的數據結構,一個二叉樹或者為空,或者由根節點、左子樹、右子樹構成,其中左子樹和右子樹都是二叉樹.每個節點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