传送门

神仙题...

和树的深度有关,由于 $BFS$ 序的性质,显然可以通过把 $BFS$ 序分成若干段来求出深度,每一段就对应某一深度从左到右的所有节点,那么如果确定了分的段数就确定了树的深度(分的段数 $+1$)

为了方便,先把 $BFS$ 序变成从 $1$ 到 $n$ 的序列, $DFS$ 序当然也要随着变一下

考虑每个位置是否可以分段,无非 $3$ 种情况:

$1.$ 此位置必须分,那么对树的深度贡献就是 $1$

$2.$ 此位置不能分,那么贡献就是 $0$

$3.$ 此位置可分可不分,那么贡献就是 $0.5$(此位置分的树的方案数和不分的树的方案数是一样的,如果分贡献 $1$,不分贡献 $0$,那么平均贡献就是 $0.5$)

考虑用 $BFS$ 序和 $DFS$ 序之间的关系求出每个位置的限制,设节点 $i$ 的 $BFS$ 序为 $bfn[i]$,$DFS$ 序为 $dfn[i]$

对于 $BFS$ 序连续的两点 $x,y=x+1$(此时已经按 $bfn$ 重新标号了),如果 $dfn[x]>dfn[y]$ ,说明 $y$ 在 $x$ 的下一层

大概图长这样:

可以发现只有这种情况才会出现 $dfn[x]>dfn[y]$ 的情况,因为如果 $x$ 和 $y$ 在同一层那么显然 $y$ 会更晚被 $dfs$ 到

所以如果 $dfn[x]>dfn[x+1]$,那么 $x$ 和 $x+1$ 之间必须分层

那么如果 $dfn[x]<dfn[x+1]$ ,是否意味着 $x$ 和 $x+1$ 之间不能分层呢,显然是不一定的,对于这种情况我们仍然无法确定是否要分层

可能有两种情况,$x$ 没有儿子, $x+1$ 是 $x$ 的兄弟;$x+1$ 是 $x$ 的儿子,还是没办法确定,而且发现不管是哪种情况都不会对之后的序列产生影响,这保证了无法确定的位置贡献是 $0.5$(这个位置不管切不切方案数都是一样的)

对于 $DFS$ 序连续的两点 $x,y$,情况比较多

如果 $x>y-1$ ($bfn[x]>bfn[y-1]$),那么说明 $y$ 是 $x$ 某个祖先的儿子:

对限制并没有影响

如果 $x==y-1$,那么 $y$ 作为 $x$ 兄弟或者儿子都是合法的

所以仍然无法确定贡献,但是同样可以发现不管是哪种情况对后面的序列都没有影响(里后面节点可以接到 $y$ 下面或者作为 $y$ 的下一个兄弟)

但是第三种情况有点意思:$x<y-1$

说明 $y$ 一定是 $x$ 的第一个儿子:

那么就是说,编号从 $x$ 到 $y-1$ 的所有节点深度差不超过1

而且可以发现,如果有分割那么在之前就被计算过了(一定存在 $k$ 使得 $dfn[x+k]>dfn[x+k+1]$ , $x+k \in [x+1,y-1]$ )

所以对于 $x<y-1$ 的情况,区间 $[x,y)$ 的位置都不能产生贡献

这个限制可以用一个差分数组维护

最后剩下的都不能确定了,贡献就是 $0.5$

最后一个问题,这些限制是必要的,但是,充分吗?

感性理解一下,很充分,如果怀疑的话打个暴力拍它几个小时,发现没问题,所以是充分的...

并不会证明限制充分 $qwq$

代码很短,但是并不好想...

设 $pos[i]$ 表示 $dfn$ 为 $i$ 的节点(其实就是 $dfn$ 的反数组)

那么对于前面最后一个限制,$x<y-1$,其实就是 $pos[i]<pos[i+1]-1$

注意一开始那些一定要分割的位置已经算过就不会再产生 $0.5$ 的贡献了

还有第一个节点一定单独要分一层

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{int x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }return x*f;
}
const int N=2e6+7;
int n;
double ans;
int dfn[N],pos[N],sum[N];//sum是差分数组
//dfn是节点的dfs序,pos是dfn的反数组,所以有 pos[dfn[i]]=i,dfn[pos[i]]=i
inline void mark(int x,int y) { sum[x]++,sum[y+1]--; }//打差分标记
int main()
{// freopen("1.in","r",stdin);n=read();ans=1; mark(1,1);//第一个节点一定要分一层for(int i=1;i<=n;i++) dfn[read()]=i;//读入初始dfs序for(int i=1;i<=n;i++) pos[dfn[read()]]=i;//用初始dfs序更新变化后的pos//上面一行不太好想。因为bfs序重标号了,原来的节点read()就变成了i,所以pos[dfn[read()]]=ifor(int i=1;i<=n;i++) dfn[pos[i]]=i;//用更新后的pos更新dfnfor(int i=1;i<n;i++)//注意i不取n
    {if(dfn[i]>dfn[i+1]) ans++,mark(i,i);//注意这里也要打标记,之后不会再产生0.5的贡献if(pos[i]<pos[i+1]-1) mark(pos[i],pos[i+1]-1);//打标记
    }int now=0;for(int i=1;i<n;i++) now+=sum[i],ans+=(now ? 0 : 0.5);//如果这个位置不确定则贡献为0.5//注意上一行i不取n,因为切的位置只有n-1个ans+=1;//深度等于分的段数+1printf("%.3lf\n%.3lf\n%.3lf",ans-0.001,ans,ans+0.001);//BZOJ上要这样输出...return 0;
}

转载于:https://www.cnblogs.com/LLTYYC/p/10818845.html

BZOJ 3244: [Noi2013]树的计数相关推荐

  1. bzoj 1211 [HNOI2004]树的计数

    [HNOI2004]树的计数 Description 一个有n个结点的树,设它的结点分别为v1, v2, -, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, ...

  2. BZOJ 1211: [HNOI2004]树的计数 purfer序列

    1211: [HNOI2004]树的计数 Description 一个有n个结点的树,设它的结点分别为v1, v2, -, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给 ...

  3. P1232 [NOI2013] 树的计数

    -调半天别的东西写错了,心力交瘁. 思路还是不会.. 具体就是二分,没想到,然后再贪心. 一直没整明白一个数它要往别的树走的条件是什么,日后研究. #include <iostream> ...

  4. [NOI2013]树的计数

    // luogu-judger-enable-o2 /* 考虑将bfs序按层分段, 每分一段就会使深度+1,所以分的段数+1就是深度 由于每种分段方式至多只能对应一种dfs序, 所以我们的目标就是求出 ...

  5. BZOJ3244 [Noi2013]树的计数 【数学期望 + 树遍历】

    题目链接 BZOJ3244 题解 不会做orz 我们要挖掘出\(bfs\)序和\(dfs\)序的性质 ①容易知道\(bfs\)序一定是一层一层的,如果我们能确定在\(bfs\)序中各层的断点,就能确定 ...

  6. BZOJ 3162 独钓寒江雪(树同构计数)

    给定一棵无根树,求其中本质不同的独立集的个数. 无根树同构. 转化成以重心为根的有根树,如果重心有两个,就在这两个重心之间插入一个点与这两个重心连边,这个点作为新的重心. 然后就成了有根树同构过程树形 ...

  7. 树的计数 Prüfer编码与Cayley公式 学习笔记

    最近学习了Prüfer编码与Cayley公式,这两个强力的工具一般用于解决树的计数问题.现在博主只能学到浅层的内容,只会用不会证明. 推荐博客:https://blog.csdn.net/moreja ...

  8. BZOj #4771. 七彩树(主席树+dfn序+lca)

    BZOj #4771. 七彩树 description solution code description 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色, ...

  9. 【BZOJ1211】【HNOI2004】树的计数(prufer序,组合数)

    Description 一个有n个结点的树,设它的结点分别为v1, v2, -, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, -, dn,编程需要 ...

最新文章

  1. 关于数据中台的深度思考与总结(超级干货)
  2. Docker最全教程——从理论到实战(九)
  3. EFLAGS 寄存器,EFLAGS 交叉引用,EFLGAS条件码
  4. python map lambda表达式_Python的lambda表达式、filter、map、reduce等函数的用法
  5. centos 创建mysql8数据库给django连接
  6. 雷军:4G 手机已清仓,全力转 5G;QQ音乐播放中途插语音广告引热议;Wine 5.9 发布 | 极客头条...
  7. java视频教程enet网络,流媒体技术原理及播放方式(浅显易懂)
  8. astype和squeeze 函数
  9. 详解单例模式线程安全
  10. 阅读-《金字塔原理》
  11. [学习报告]《LeetCode零基础指南》第三讲循环-gyro
  12. 关于汽车人转型,“正能量”故事看腻了,今天来一篇“负能量”的
  13. Spring Data JPA 多条件判空查询
  14. DIY一个UNISOLDER焊台无线红外休眠座
  15. ZY Player 2.3.5 中文版 (全网视频播放器)
  16. 【Java】JavaFx桌面编程整理
  17. 梅赛德斯-奔驰集结全球、中国首秀和上市车型亮相2023上海车展
  18. 药店计算机信息系统知识培训,的药店信息管理系统.docx
  19. 计算机三维建模概述论文,基于视觉的三维场景建模研究与实现-计算机科学与技术专业毕业论文.docx...
  20. python 除了 不会生猴子外 其他都可以

热门文章

  1. 装车机器人_智造春天脚步近 青岛这家机器人公司着手打造模块化、标准化技术平台...
  2. h5现实手机管理系统_webflash,后台管理系统
  3. android按钮点击变化,Android实现按钮点击效果(第一次点击变色,第二次恢复)...
  4. conda deactivate python3_python3的配置解决
  5. c语言作业做出金山打字功能,goldmountain.c
  6. vant 下拉框样式_使用 Vue 的 Vant.js List 列表组件实现无限下拉
  7. linux中 ln -s 软链接
  8. Springboot : RequestContextHolder
  9. 浏览器的referer是服务器修改的吗,利用浏览器调整http的referer
  10. windows kernel 可以直接读写文件系统资料吗_嵌入式杂谈之文件系统