zoukankan      html  css  js  c++  java
  • BZOJ3244 [Noi2013]树的计数 【数学期望 + 树遍历】

    题目链接

    BZOJ3244

    题解

    不会做orz

    我们要挖掘出(bfs)序和(dfs)序的性质
    ①容易知道(bfs)序一定是一层一层的,如果我们能确定在(bfs)序中各层的断点,就能确定深度
    ②由于(bfs)序和(dfs)序儿子遍历顺序是一样的,所以(bfs)序同一层的点,在(dfs)序中顺序也一样,如果存在(u,v)(bfs)中相邻,而在(dfs)序中逆序,那么(u,v)之间一定有断点
    (dfs)序中相邻的两个点(u,v)之间(v)要么为(u)的儿子,要么为(u)某个祖先的儿子,若(v)(bfs)序大于(u)的,那么它们之间之多存在一个断点
    ④在③中确定的限制区间内,如果包含②中确定的断点,那么就可以确定其余点一定不分层。否则区间内点的顺序一定与(dfs)序一样,由于区间端点(dfs)序中相邻,所以这个区间只可能限制了一个断点

    综上:
    ①若(bfs)序中相邻的在(dfs)序中逆序,必有断点
    (dfs)序中相邻的在(bfs)序中正序,之间最多一个断点,要么已确定期望(1)个,要么就只有一个不确定,期望(0.5)
    (1)只有必有断点

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 200005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int dfs[maxn],bfs[maxn],pos[maxn],id[maxn],x[maxn],sum[maxn],D[maxn],n;
    int main(){
    	n = read();
    	REP(i,n) dfs[i] = read();
    	REP(i,n) bfs[i] = read(),id[bfs[i]] = i;
    	REP(i,n) dfs[i] = id[dfs[i]],pos[dfs[i]] = i;
    	x[1] = 1;
    	for (int i = 2; i < n; i++)
    		if (pos[i] > pos[i + 1]) x[i] = 1;
    	for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + x[i];
    	for (int i = 1; i < n; i++)
    		if (dfs[i] < dfs[i + 1]){
    			if (sum[dfs[i + 1] - 1] - sum[dfs[i] - 1]){
    				D[dfs[i]]++;
    				D[dfs[i + 1]]--;
    			}
    		}
    	int tot = 0;
    	for (int i = 1; i < n; i++){
    		tot += D[i];
    		if (!x[i] && tot) x[i] = 2;
    	}
    	double ans = 1.0;
    	for (int i = 1; i < n; i++){
    		if (x[i] == 1) ans += 1.0;
    		else if (!x[i]) ans += 0.5;
    	}
    	printf("%.3lf
    %.3lf
    %.3lf
    ",ans - 0.001,ans,ans + 0.001);
    	return 0;
    }
    
    
  • 相关阅读:
    Qt -- 鼠标移入移出事件 enterEvent、leaveEvent
    QT -- QPainter介绍
    Qt -- 浅析QFontMetrics 获取字体宽度,高度
    函数声明后面的const用法
    QT -- 读取file数据/写数据到file
    QT -- QLineEdit按下回车键获取信息
    C++ -- fgets,fputs,fputc,fgetc总结
    QT -- QString / std::string转换为const char*
    C++ -- fopen函数用法
    HTML DOM树
  • 原文地址:https://www.cnblogs.com/Mychael/p/9044077.html
Copyright © 2011-2022 走看看