• [NOI2013]树的计数(概率期望×树的遍历)


    题目链接

    首先我们发现我们要求的就是数的期望高度,然后根据期望的线性性我们可以把它分成几层。

    观察到这个树的编号是无所谓的,我们可以给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;
    
  • 相关阅读:
    linux安装nginx
    python-- python threadpool 的前世今生
    如何用 Go 实现热重启
    使用expect快速登录线上机器
    curl 使用手册
    date命令时间戳和时间之间的转换
    linux设置程序运行超时时间
    你见过的最全面的python重点
    golang学习之旅:使用go语言操作mysql数据库
    Python多进程编程
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/13715480.html
Copyright © 2020-2023  润新知