給定一棵 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序,我們想要知道,...