zoukankan      html  css  js  c++  java
  • [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;
    
  • 相关阅读:
    Sql server 中count(1) 与 sum(1) 那个更快?
    Sql server 中count() 与 sum() 的区别
    ASP.Net Core 运行错误 Http Error 502.5 解决办法
    什么是语法糖?
    int和Integer有什么区别?如何相互转换呢?
    面向对象的基本特征有哪些方面?
    谈谈final finally finalize区别
    Overload和Override的区别
    String s=new String(“xyz”);创建了几个String Object?
    Gc是什么?为什么要有Gc?
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/13715480.html
Copyright © 2011-2022 走看看