题目概括:
给出树的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大神 轻松地构造了一个数据把没线段树的卡了

代码:

 #include <cstdio>
const int NN=;
int n,dfs[NN],bfs[NN],rk[NN],max[NN],tree[NN*];
double ans,save;
inline int minn(int x,int y){ return x<y ? x : y; }
void build(int l,int r,int rt){
if (l==r){
tree[rt]=dfs[l];
return;
}
int mid=(l+r)/;
build(l,mid,rt*);
build(mid+,r,rt*+);
tree[rt]=minn(tree[rt*],tree[rt*+]);
}
int min(int l,int r,int rt,int x,int y){
if (x<=l && r<=y) return tree[rt];
int mid=(l+r)/,res=n;
if (x<=mid) res=minn(res,min(l,mid,rt*,x,y));
if (mid<y) res=minn(res,min(mid+,r,rt*+,x,y));
return res;
}
int main(){
freopen("bz3244.in","r",stdin);
freopen("bz3244.out","w",stdout);
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&dfs[i]);
for (int i=;i<=n;i++) scanf("%d",&bfs[i]);
for (int i=;i<=n;i++) rk[bfs[i]]=i;
for (int i=;i<=n;i++) dfs[i]=rk[dfs[i]];
for (int i=;i<=n;i++) rk[dfs[i]]=i;
for (int i=;i<=n;i++) max[i]=max[i-]>dfs[i] ? max[i-] : dfs[i];
build(,n,);
ans=;
for (int i=;i<n;i++){
if (i== || rk[i+]<rk[i]) ans=ans++save;
else if (rk[i+]==rk[i]+){
if (max[rk[i]]<=i+) save=save+0.5;
}else if (min(,n,,rk[i],rk[i+])<i) save=;
}
ans+=save;
printf("%.3f\n",ans-0.001);
printf("%.3f\n",ans);
printf("%.3f\n",ans+0.001);
fclose(stdin);
fclose(stdout);
}

【noi2013】【bz3244】树的计数的更多相关文章

  1. 「NOI2013」树的计数 解题报告

    「NOI2013」树的计数 这什么神题 考虑对bfs重新编号为1,2,3...n,然后重新搞一下dfs序 设dfs序为\(dfn_i\),dfs序第\(i\)位对应的节点为\(pos_i\) 一个暴力 ...

  2. loj#2665. 「NOI2013」树的计数

    目录 题目链接 题解 代码 题目链接 loj#2665. 「NOI2013」树的计数 题解 求树高的期望 对bfs序分层 考虑同时符合dfs和bfs序的树满足什么条件 第一个点要强制分层 对于bfs序 ...

  3. 【BZOJ3244】【NOI2013】树的计数(神仙题)

    [BZOJ3244][NOI2013]树的计数(神仙题) 题面 BZOJ 这题有点假,\(bzoj\)上如果要交的话请输出\(ans-0.001,ans,ans+0.001\) 题解 数的形态和编号没 ...

  4. UOJ#122【NOI2013】树的计数

    [NOI2013]树的计数 链接:http://uoj.ac/problem/122 按BFS序来,如果$B_i$与$B_{i-1}$必须在同一层,那么贡献为0,必须在不同层那么贡献为1,都可以贡献为 ...

  5. UOJ #122 【NOI2013】 树的计数

    题目链接:树的计数 这道题好神啊……正好有人讲了这道题,那么我就写掉吧…… 首先,为了方便考虑,我们可以把节点重标号,使得\(bfs\)序变成\(1,2,3,\dots,n\),那么显然树的深度就是\ ...

  6. 【NOI2013】树的计数

    Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...

  7. 【LOJ】 #2665. 「NOI2013」树的计数

    题解 我们统计深度对于bfs序统计,树结构出现分歧的地方必然是BFS序的最后一段,这个最后一段同时还得是dfs序上连续的一段 如果不是bfs序的最后一段,那么必然下一层会有节点,如果树结构分歧了,那么 ...

  8. [UOJ#122][NOI2013]树的计数

    [UOJ#122][NOI2013]树的计数 试题描述 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的 DFS 序以及 BFS 序.两棵不同的树的 DFS 序 ...

  9. 树的计数 + prufer序列与Cayley公式 学习笔记

    首先是 Martrix67 的博文:http://www.matrix67.com/blog/archives/682 然后是morejarphone同学的博文:http://blog.csdn.ne ...

  10. 【BZOJ】【1211】【HNOI2004】树的计数

    Prufer序列+组合数学 嗯哼~给定每个点的度数!求树的种数!那么很自然的就想到是用prufer序列啦~(不知道prufer序列的……自己再找找资料吧,这里就不放了,可以去做一下BZOJ1005明明 ...

随机推荐

  1. HDOJ2009求数列的和

    求数列的和 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  2. request常用方法小结

    HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息. req ...

  3. Javascript之三种按钮点击事件

    学习Javascript必须要先掌握基本的事件方法和语法,这些都是我们学过的也是最基本的.以前忘了总结,所以现在回顾,综合地总结一下,温故而知新. Javascript有三种按钮点击事件,分别为ale ...

  4. php对UTF8字体串进行单字分割返回数组

    在网上查了很多字符串分割方法,都无法正确对UTF8字符串进行正确分割返回单个字符的数组.经过对FTU8编码的分析写出了下面的方法对UTF8进行分割.本人测试可用.本方法只支持UTF8编码的,其它编码转 ...

  5. 第二篇、为UITableViewCell 高度自适应加速 缓存cell的高度

    通过NSCache缓存已经算好的行高 @interface ZHCellHeightCalculator : NSObject //系统计算高度后缓存进cache -(void)setHeight:( ...

  6. Block深入浅出

    研究工具 clang 为了研究编译器的实现原理,我们需要使用 clang 命令.clang 命令可以将 Objetive-C 的源码改写成 C / C++ 语言的,借此可以研究 block 中各个特性 ...

  7. 在button中加入一个view图片

    #import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...

  8. C# to Maxscript

    I figured I’d do a quick tutorial about something a little more difficult, but still very important. ...

  9. 20141015--for语句2

    for语句,打印等腰三角形: 第一种方法:(使用for语句嵌套) 第二种方法:(定义string型变量) 以下是其他形状的等腰三角形: (穿插使用了for语句嵌套,定义string型)

  10. 委托[delegate]_C#

    委托(delegate): 委托声明定义了一种类型,它用一组特定的参数以及返回类型来封装方法.对于静态方法,委托对象封装要调用的方法.对于实例方法,委托对象同时封装一个实例和该实例上的一个方法.如果您 ...