[bzoj3244][noi2013]树的计数 题解
UPD: 那位神牛的题解更新了,在这里。
----------------------------------------------------------------------------------------------------
被这题虐了好久……本来是看这个题解,然后晕乎乎的,没怎么看懂……然后YGW巨神质疑那个程序,于是就举出了一个反例……(rzO Orz)。于是本蒟蒻就顺着那个题解的思路和YGW的反例弄出了一种奇葩的方法……
我们在BFS序上分割,分出每一层。这样一种分割方案对应一种树的形态。
其实,分割方案会有不同,原因在于存在某些点,他们既可以做与他相邻的点的儿子,也可以做兄弟。那么他们对ans的贡献是0.5。而那些只能做儿子的点就只能被分配到下一层,所以对ans的贡献是1.0;其它的点对分层方案没有影响,对ans就没有贡献。于是关键在于如何找到这些点。
我们把BFS序编为1..n,以此重标号DFS序。
我们从1到n遍历BFS序,根据dfs序一个一个判断。
考虑那些既可以做兄弟也可以做儿子的点。
这些点必须满足既可以做兄弟也可以做儿子(废话- -)。
可以发现,那些点刚好在BFS和DFS序都是连续的。但是这还不够。我们还必须满足这个点可以分配到下一层(因为如果可以被分配到下一层就可以做兄弟)。于是考虑两个情况:
1.下一层有一个点的BFS序>当前点。
2.当前层有一个点的BFS序>当前点,且这个点必须在当前层。(注:有一种情况存在一个点的BFS序>当前点,但是不一定要在当前层,这种情况不影响当前点的分配方案。)
这两个情况下当前点都只能被分配到当前层。
第一种等价于dfs序<当前点的点中存在一个bfs序>当前点的点。(可以用前缀最值判断)
第二种等价于在dfs序中这个点的到前一个点之间有一个bfs序<当前点,这相当于限制了当前点与前一个点不是同一个点的儿子。(可以用线段树判断,否则要n^2,完全可以构造数据卡掉,如bfs:1 2 3 4 5 6 7 8 ... dfs:1 3 5 7 ... 2 4 6 8 ...)
当排除了上面两种情况后,当前点就可以放到下面去。且把当前点放到下面去对后面所有的点的分配是没有影响的,这样保证了正确性。
考虑那些只能做儿子的点。
这种情况只出现在当前点的dfs序<上一个点的dfs序。
最后贴一下卡掉那个代码的数据和我的代码
9
1 2 4 5 6 7 9 8 3
1 2 3 4 5 6 7 8 9
/**************************************************************
Problem: 3244
User: lazycal
Language: C++
Result: Accepted
Time:292 ms
Memory:7056 kb
****************************************************************/
#include <cstdio>
#include <algorithm>
const int N = 200000 + 9;
int Max[N],Min[N*4],rk[N],dfs[N],bfs[N],n;
void build(const int idx,const int l,const int r)
{
if (l == r) return (void)(Min[idx] = dfs[l]);
build(idx * 2,l,(l+r)/2);
build(idx*2+1,(l+r)/2+1,r);
Min[idx] = std::min(Min[idx*2],Min[idx*2+1]);
}
int MIN(const int idx,const int l,const int r,const int L,const int R)
{
if (L <= l && r <= R) return Min[idx];
int mid = (l + r)/2,res = 0x7fffffff;
if (L <= mid) res = std::min(res,MIN(idx * 2,l,mid,L,R));
if (mid < R) res = std::min(res,MIN(idx*2+1,mid+1,r,L,R));
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("3244.in","r",stdin);
freopen("3244.out","w",stdout);
#endif
scanf("%d",&n);
for (int i = 1; i <= n; ++i) {
scanf("%d",dfs + i);
rk[dfs[i]] = i;
}
for (int i = 1; i <= n; ++i) {
scanf("%d",bfs + i);
dfs[rk[bfs[i]]] = i;
}
for (int i = 1; i <= n; ++i) {
Max[i] = std::max(Max[i - 1],dfs[i]);
rk[dfs[i]] = i;
}
build(1,1,n);
int ans = 2,tmp = 0;
for (int i = 1; i < n; ++i) {
if (i == 1 || rk[i + 1] < rk[i]) ans += tmp + 2,tmp = 0;
else if (rk[i] + 1 == rk[i + 1] && Max[rk[i]] < i + 1) ++tmp;
else if (MIN(1,1,n,rk[i] + 1,rk[i + 1] - 1) < i) tmp = 0;
}
ans += tmp;
printf("%.3f\n%.3f\n%.3f\n",ans/2.0-0.001,ans/2.0,ans/2.0+0.001);
}
[bzoj3244][noi2013]树的计数 题解的更多相关文章
- BZOJ3244 NOI2013树的计数(概率期望)
容易发现的一点是如果确定了每一层有哪些点,树的形态就确定了.问题变为划分bfs序. 考虑怎样划分是合法的.同一层的点在bfs序中出现顺序与dfs序中相同.对于dfs序中相邻两点依次设为x和y,y至多在 ...
- BZOJ3244 [Noi2013]树的计数 【数学期望 + 树遍历】
题目链接 BZOJ3244 题解 不会做orz 我们要挖掘出\(bfs\)序和\(dfs\)序的性质 ①容易知道\(bfs\)序一定是一层一层的,如果我们能确定在\(bfs\)序中各层的断点,就能确定 ...
- [BZOJ3244][NOI2013]树的计数
这题大家为什么都写O(NlogN)的算法呢?…… 让本蒟蒻来写一个O(N)的吧…… 首先还是对BFS序和DFS序重编号,记标好的DFS序为d[1..n].令pos[x]为x在d[]中出现的位置,即po ...
- [UOJ#122][NOI2013]树的计数
[UOJ#122][NOI2013]树的计数 试题描述 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的 DFS 序以及 BFS 序.两棵不同的树的 DFS 序 ...
- 【BZOJ3244】【UOJ#122】【NOI2013]树的计数
NOI都是酱的题怎么玩啊,哇.jpg 原题: 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的 ...
- [bzoj3244] [洛谷P1232] [Noi2013] 树的计数
Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...
- BZOJ3244/UOJ122 [Noi2013]树的计数
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 3244: [Noi2013]树的计数 - BZOJ
Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...
- bzoj 3244: [Noi2013]树的计数
Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...
随机推荐
- 【BZOJ】1419 Red is good
[算法]期望DP [题解]其实把状态表示出来就是很简单的期望DP. f[i][j]表示i张红牌,j张黑牌的期望. i=0时,f[0][j]=0. j=0时,f[i][0]=i. f[i][j]=max ...
- CSUST选拔赛题解
本鶸鸡于本月10号参加了蔽校的选拔赛,成绩差的死,大部分的题都是赛后花了好长时间才补出来的,其中有些题还是靠QAQorz大佬帮忙才能解决,感谢Qls对我的帮助~接下来就附带上我的暴力题解,大佬们有更好 ...
- hdu 1217 Arbitrage (spfa算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1217 题目大意:通过货币的转换,来判断是否获利,如果获利则输出Yes,否则输出No. 这里介绍一个ST ...
- Linux目录结构与文件权限——(五)
1.目录结构
- Python第三方库matplotlib(2D绘图库)入门与进阶
Matplotlib 一 简介: 二 相关文档: 三 入门与进阶案例 1- 简单图形绘制 2- figure的简单使用 3- 设置坐标轴 4- 设置legend图例 5- 添加注解和绘制点以及在图形上 ...
- handle_level_irq 与handle_edge_irq 的区别【转】
转自:http://blog.csdn.net/xavierxiao/article/details/6087277 版权声明:本文为博主原创文章,未经博主允许不得转载. Linux 里, handl ...
- 3.FireDAC组件快照
TFDManager 连接定义和Connect连接管理 TFDConnection 数据库连接组件,支持三种连接方式:1.持久定义(有一个唯一名称和一个配置文件,可以由FDManager管理) 例: ...
- C中级 数据序列化简单使用和讨论 (二)
引言 - 一种更好的方式 其实不管什么语言, 开发框架都会遇到序列化问题. 序列化可以理解为A 和 B 交互的一种协议. 很久以前利用 printf 和 scanf 的协议实现过一套序列化问题. C ...
- Cause: java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.ibatis.mapping.MappedStatement
我用的是pagehelper 4.2.0,利用其进行表单的分页处理并进行展示,在第一次执行的时候能够看到分页后的结果,刷新一下第二次就显示不出来,控制台出现: Cause: java.lang.Cla ...
- 关于:TypeConverter 无法从 System.String 转换
TypeConverter 无法从 System.String 转换 处理方法: 1: [DX Support Team: The issue was resolved by its Owner] i ...