• 【noi2013】【bz3244】树的计数


    题目概括:
    给出树的dfs、bfs序 求树的期望高度

    题解:
    由于我比较懒 先copy一段百度文库的题解~
    void copy(){
    我们可以发现,所求的树之所以会有很多种,是因为出现了这种情况:
    对于A、B,A既可以做B的兄弟,又可以做B的父亲。
    (显然其中的一个前提是A、B在dfs、bfs序列中都必须相邻)
    而这样除去A,B的关系外,对于其他任何节点之间的关系都没有任何影响。 所以这中情况对答案的贡献是0.5。
    然后对于A,B,如果A只能是B的父亲(也就是BFS序列中的断层),那么对答案的贡献为1。
    所以,我们只要找出来以上两种关系,最后将贡献值加起来就是答案。
    }
    这个题解木有具体写加0.5的情况 so 下面具体说一下 什么情况加0.5

    我们先把bfs序换成1..n 假设A、B 为i、i+1
    首先 他们的dfs&bfs序必须相邻且位置先后一样(dfs[i]+1==dfs[i+1])
    然后 还要满足以下条件
    1.dfs序<i+1的所有点的bfs序都要<bfs[i+1]
    形象地说就是dfs时在i+1点的前面点的深度不能超过i+1的深度
    证明:
    假设点dfs[j]<dfs[i+1] && bfs[j]>bfs[i+1] 且j的深度==i+1的深度+1
    如果 i+1做了i的儿子 那么i+1就会出现在j的同一层 且在j的后面
    也就是 bfs[j]<bfs[i+1] 矛盾
    2.假设点j为必须断层的点的前一点(该层最后一点)
    对于满足 dfs[i+1]<dfs[x]<dfs[j] 的所有x 必须满足 bfs[x]>=bfs[i+1]
    就是说可能与i+1同层的点 必须是i+1的兄弟 可能不大好理解 简单解释一下
    如果j不是i+1的兄弟 j的老爸的bfs序肯定<bfs[i+1]
    证明:
    条件:bfs[j]>bfs[i+1] 且i+1、j同层
    如果i+1做了i的儿子 那么i+1就会在j的下一层
    也就是 bfs[j]<bfs[i+1] 矛盾

    优化:
    如果每个点都要找到条件2的断层点 就有可能导致n^2的复杂度
    再介绍下由 sto AK大神 提供的小优化
    可以开个临时的变量累加所有的0.5 如果在断层前遇到某个i和i+1不是兄弟 就把临时变量清0
    遇到断层时ans+=临时变量
    还有 判断条件2的时候可以用线段树优化一下 虽然官方的数据卡不掉 但追求完美的AK大神 轻松地构造了一个数据把没线段树的卡了

    代码:

     1 #include <cstdio>
     2 const int NN=200001;
     3 int n,dfs[NN],bfs[NN],rk[NN],max[NN],tree[NN*4];
     4 double ans,save;
     5 inline int minn(int x,int y){ return x<y ? x : y; }
     6 void build(int l,int r,int rt){
     7     if (l==r){
     8         tree[rt]=dfs[l];
     9         return;
    10     }
    11     int mid=(l+r)/2;
    12     build(l,mid,rt*2);
    13     build(mid+1,r,rt*2+1);
    14     tree[rt]=minn(tree[rt*2],tree[rt*2+1]);
    15 }
    16 int min(int l,int r,int rt,int x,int y){
    17     if (x<=l && r<=y) return tree[rt];
    18     int mid=(l+r)/2,res=n;
    19     if (x<=mid) res=minn(res,min(l,mid,rt*2,x,y));
    20     if (mid<y) res=minn(res,min(mid+1,r,rt*2+1,x,y));
    21     return res;
    22 }
    23 int main(){
    24     freopen("bz3244.in","r",stdin);
    25     freopen("bz3244.out","w",stdout);
    26     scanf("%d",&n);
    27     for (int i=1;i<=n;i++) scanf("%d",&dfs[i]);
    28     for (int i=1;i<=n;i++) scanf("%d",&bfs[i]);
    29     for (int i=1;i<=n;i++) rk[bfs[i]]=i;
    30     for (int i=1;i<=n;i++) dfs[i]=rk[dfs[i]];
    31     for (int i=1;i<=n;i++) rk[dfs[i]]=i;
    32     for (int i=1;i<=n;i++) max[i]=max[i-1]>dfs[i] ? max[i-1] : dfs[i];
    33     build(1,n,1);
    34     ans=1;
    35     for (int i=1;i<n;i++){
    36         if (i==1 || rk[i+1]<rk[i]) ans=ans+1+save;
    37         else if (rk[i+1]==rk[i]+1){
    38             if (max[rk[i]]<=i+1) save=save+0.5;
    39         }else if (min(1,n,1,rk[i],rk[i+1])<i) save=0;
    40     }
    41     ans+=save;
    42     printf("%.3f
    ",ans-0.001);
    43     printf("%.3f
    ",ans);
    44     printf("%.3f
    ",ans+0.001);
    45     fclose(stdin);
    46     fclose(stdout);
    47 }
    View Code
  • 相关阅读:
    HDU-1421 搬寝室(递推,DP,数学)2017寒假集训
    HDU-2577 How to Type(递推,DP)(水)2017寒假集训
    POJ-1088 滑雪(DP,二维LIS,记忆化)2017寒假集训
    CSUST-17级集训队选拔赛解题报告
    (十六)服务化:微服务架构,必须搞定高可用!
    (十五)服务化:微服务架构,粒度多少合适?
    (十四)服务化:微服务架构,究竟解决什么问题?
    (十三)本章小结:百万流量,这些技术够用了
    (十二)性能优化:读写分离,前台与后台分离
    (十一)性能优化:动静分离,互联网优化利器?
  • 原文地址:https://www.cnblogs.com/g-word/p/3288675.html
Copyright © 2020-2023  润新知