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