BZOJ3244 NOI2013樹的計數

2021-07-08 09:38:17 字數 1846 閱讀 7392

給定一棵 n(

n<=

200000

) 個節點的樹的 df

s、bf

s `序,求所有滿足要求的樹的平均深度。

考慮到 bf

s 序的性質,bf

s 在前的點的深度一定小於等於後面的點。所以我們考慮根據 bf

s 序計算答案。

首先根據 bf

s 序給樹上的點重編號,按 bf

s 序的先後編成 1,

2,..

.,n ,考慮相鄰的點

i 對答案的貢獻,如果它和 i−

1必須在不同的層,那麼對答案的貢獻為

1 ,如果它和 i−

1必須在同一層,那麼對答案的貢獻為

0 ,否則為

0.5,最後只需要把所有的貢獻加起來就行了 (1,

2號點的

貢獻應該

強制為1

)。 必須不在同一層很好判斷,考慮一下必須在同一層的情況,如果點i在 df

s 序中的位置在點 i−

1 前面的話,那麼就一定在不同層。

否則只剩下在必須在同一層或者都可以。

在同一層和不同層都可以的情況,顯然需要滿足 df

s 序中 i−

1,i 兩個點必須是連續的。我們畫圖發現,如果在一棵按 bf

s 序編號的樹中,點

i 可以變作 i−

1的兒子的並且不改變 df

s,bf

s 序的話,只能是

i 變換後,

i所在的那一層只有

i 乙個點並且 i,

i−1應該有共同的父親,那麼這個條件等價於 1∼

i−1 號點在 df

s 序中 1∼

l 的一段和 r∼

n 的一段,也就是說在 df

s 序中必須是前面一段最後一段。然後其他情況就是必須在同一層了。

最後記住 bz

oj上不知道為什麼需要輸出三行,分別為an

s−0.001,a

ns,a

ns+0.001

#include 

#include

#include

#include

#include

#include

using

namespace

std;

int n;

int dfs[200010]=;

int bfs[200010]=;

int in[200010]=;

int max[200010]=;

int hash[200010]=;

int main()

for(int i=1;i<=n;i++)

for(int i=1;i<=n;i++)

in[dfs[i]]=i;

max[1]=dfs[1];

for(int i=2;i<=n;i++)

max[i]=max(max[i-1],dfs[i]);

double ans=2;

int l=2,r=n+1;

hash[1]=hash[2]=1;

for(int i=3;i<=n;i++)

hash[in[i]]=1;

for(;l1]==1;l++);

for(;l1]==1;r--);

}printf("%.3lf\n",ans);

//in bzoj printf("%.3lf\n%.3lf\n%.3lf\n",ans-0.001,ans,ans+0.001);

return

0;}

BZOJ3244 NOI2013 樹的計數

我們知道一棵有根樹可以進行深度優先遍歷 dfs 以及廣度優先遍歷 bfs 來生成這棵樹的dfs序以及bfs序。兩棵不同的樹的dfs序有可能相同,並且它們的bfs序也有可能相同,例如下面兩棵樹的dfs序都是1 2 4 5 3,bfs序都是1 2 3 4 5 現給定乙個dfs序和bfs序,我們想要知道,...

BZOJ3244 Noi2013 樹的計數

這題其實我還不是很懂為什麼滿足了這兩個性質就一定合法qaq 先將所有點按其bfs序重新標號 我們令dfn i 表示i的dfs序,bfn i 表示dfs序為i的點的bfs序 考慮怎麼計算答案,我們令dep i 表示點i所在樹中的層數,那麼對dep i 做個差分,a i a i a i 1 a 1 a ...

bzoj3244 Noi2013 樹的計數

我們知道一棵有根樹可以進行深度優先遍歷 dfs 以及廣度優先遍歷 bfs 來生成這棵樹的dfs序以及bfs序。兩棵不同的樹的dfs序有可能相同,並且它們的bfs序也有可能相同,例如下面兩棵樹的dfs序都是1 2 4 5 3,bfs序都是1 2 3 4 5 現給定乙個dfs序和bfs序,我們想要知道,...