• NOI2013 树的计数


    NOI2013 树的计数

    给定一个dfs序和bfs序,求解符合这两个条件的所有树的平均树高。

    思路

    如果我们能够给bfs序中每一段区间分层,然后再去对应dfs序,不难发现可以唯一确定一棵树,即在dfs的过程中,前后两个节点的关系可以按照层数来判断,分为儿子或者是某一层祖先的另外一个儿子。

    而给bfs序分层的时候我们需要满足一些限制:

    1. bfs序中同一层在dfs中访问顺序必须严格按照bfs的访问顺序来。
    2. dfs中每一次只能往下走一层或者是往上走若干层或者还停留在这一层。
    3. 1号点必须要分层。

    接下来考虑怎么求解树高,bfs按照限制分完层之后会有一些断点,我们可以求出在满足限制的情况下每一个点成为端点的期望是多少,最后根据期望的线性性直接相加就可以得到最后的答案。

    考虑如何去满足这些限制。

    从1号限制的逆否命题可以退出,如果相邻的两个点在dfs中没有按照编号的顺序来,那么它们一定不在同一层,即pos[i]>pos[i+1],那么可以肯定i一定是断点,不难发现满足了这个限制就满足了1号限制。

    1. 在dfs序中相邻的两个点d[i],d[i+1],如果d[i+1] < d[i],那么i+1一定是i某一个祖先的另一个儿子,它们之间的断点个数是可以任意的。

    2. 如果d[i+1]>d[i]+1,它们一定不是兄弟的关系,也就是这两个点只能做父子,并且它们之间的断点个数一定为1,也就是我们可以标记这中间所有的点,它们都是已经确定的。

    3. 如果d[i+1]=d[i]+1,它们既可以做父子又可以做兄弟,它们之间的关系也是任意的。

    但是上面1.3情况的任意取值都受2情况的影响,我们标记所有2情况影响的点,然后对于剩下的没有标记的点就可以任意取值,期望为0.5。

    最后的答案就是确定为1的点加上期望为0.5的点。

    // luogu-judger-enable-o2
    /*=======================================
     * Author : ylsoi
     * Time : 2019.6.18
     * Problem : luogu1232
     * E-mail : ylsoi@foxmail.com
     * ====================================*/
    #include<bits/stdc++.h>
    
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
    #define debug(x) cout<<#x<<"="<<x<<" "
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    typedef long long ll;
    
    using namespace std;
    
    void File(){
        freopen("luogu1232.in","r",stdin);
        freopen("luogu1232.out","w",stdout);
    }
    
    template<typename T>void read(T &_){
        _=0; T f=1; char c=getchar();
        for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
        for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0');
        _*=f;
    }
    
    string proc(){
        ifstream f("/proc/self/status");
        return string(istreambuf_iterator<char>(f),istreambuf_iterator<char>());
    }
    
    const int maxn=2e5+10;
    int n,b[maxn],d[maxn],pb[maxn],pd[maxn],vis[maxn];
    double ans;
    
    int main(){
        //File();
    
        read(n);
        REP(i,1,n)read(d[i]);
        REP(i,1,n)read(b[i]),pb[b[i]]=i;
        REP(i,1,n)d[i]=pb[d[i]],pd[d[i]]=i;
        REP(i,2,n-1){
            if(pd[i]>pd[i+1])ans+=1,++vis[i],--vis[i+1];
            if(d[i]+1<d[i+1])++vis[d[i]],--vis[d[i+1]];
        }
        REP(i,3,n)vis[i]+=vis[i-1];
        REP(i,2,n-1)if(!vis[i])ans+=0.5;
        printf("%.3lf
    ",ans+2);
    
        return 0;
    }
    
  • 相关阅读:
    指针系统学习5-对使用字符指针变量和字符数组的讨论
    指针系统学习4-字符串与指针
    指针系统学习3-多维数组与指针
    指针系统学习2
    指针系统学习1
    你视为意见领袖的大 V,可能只是个僵尸号
    phpinfo()
    用shell脚本守护后台进程
    mysql命令(command)
    MySQL数据库视图(view),视图定义、创建视图、修改视图
  • 原文地址:https://www.cnblogs.com/ylsoi/p/11047050.html
Copyright © 2020-2023  润新知