首先我们发现我们要求的就是数的期望高度,然后根据期望的线性性我们可以把它分成几层。
观察到这个树的编号是无所谓的,我们可以给bfs序重新编号成 (1) 到 (n),同时改变dfs序,这样不会有影响。
又发现bfs是按层来搞的,所以我们下一步就是分层,也就是把bfs划分成几个区间,每个区间在一层。
显然这不可能是随便分层,有一些限制。我们用一个数组来表示 (i) 和 (i+1) 直接有没有分割,如果为 (0) 即为不确定。
1,(1) 和 (2) 之间一定有分隔。这很显然。
2,假设 (d_i) 是 (i) 在dfs序中的位置。若 (d_i>d_{i+1}) 说明dfs的过程中先遍历到 (i+1) 再遍历到 (i),而如果他们在同一层中则不可能(因为是按顺序排的),所以它们一定不在同一层中,答案加一。
3,还有这第三个限制,也是比较难想到的。假设 (dfn_i) 是dfs序,若 (dfn_i+1<dfn_{i+1}),说明 (dfn_{i+1}) 的 深度最多比 (dfn{i}) 多1,所以 (dfn_{i}) 与 (dfn_{i+1}) 之间最多放一个分隔线,而枚举几种情况发现期间必有一条分隔线,所以这一段不得再有其他分隔线。
最后,如果还是可填可不填的答案就加0.5。
namespace Solve{
const int MAXN = 200010;
static int n, dfn[MAXN], bfn[MAXN], pos[MAXN], s[MAXN], d[MAXN];
static double ans;
void MAIN() {
read(n);
for (int i = 1; i <= n; i++) read(dfn[i]);
for (int i = 1; i <= n; i++) read(bfn[i]), pos[bfn[i]] = i;
for (int i = 1; i <= n; i++) dfn[i] = pos[dfn[i]], d[dfn[i]] = i;
s[1]++; s[2]--;
ans = 2.0;//注意第一个点算一层
for (int i = 1; i < n; i++) {
if (d[i] > d[i + 1]) {
s[i]++;
s[i + 1]--;
ans += 1.0;
}
if (dfn[i] + 1 < dfn[i + 1]) {
s[dfn[i]]++;
s[dfn[i + 1]]--;
}
}
for (int i = 1; i < n; i++) {
s[i] += s[i - 1];
if (s[i] == 0) {
ans += 0.5;
}
}
printf("%.3lf
", ans);
}
} using namespace Solve;