题意:给你DFS序和BFS序,求树的期望高度。

解:先分析性质。

考虑到BFS序是分层的,DFS序的子树是一段,那么我们遍历BFS序并在DFS序上标记对应点的话,就会发现BFS序每一层都会把若干棵子树每个都分成若干个小子树,且换层的时候一定会是DFS序上第一个非空位置。

设每个点的期望深度为hi,那么就是要求BFS序最后一个点的h。考虑每个点的深度怎么算。如果当前点不是新一层的开头,那么它的h一定等于他在BFS序前面一个点的深度。如果是开头,那么就要等于它父亲的深度 + 1,我们可以在DFS序上把每个点的子树染色以查明该点的父亲。如果这两种情况都有可能,那么h就是这两种情况的平均数。

考虑什么时候只可能是一种情况。

当这个点在DFS序上的位置前于BFS序上前一个点在DFS序上的位置的时候,当前点一定是新一层的开头。

当这个点在DFS序上的位置后与BFS序上前一个点在DFS序上的位置的时候:如果这个点和BFS上前一个点在DFS序上的位置不相邻,那么这两个点一定在同一层。

相邻的时候,如果当前点在DFS序的前面还有空位,那么一定在同一层。否则考虑这个子树后面还有没有空位,如果有也一定在同一层,因为要换层的话一定要把后面的每个都走一遍。

实现的时候就用线段树维护颜色和区间和。

 #include <bits/stdc++.h>

 const int N = ;

 int col[N << ], sum[N << ];
int d[N], b[N], pos[N];
double h[N]; inline void pushdown(int o) {
if(!col[o]) return;
col[o << ] = col[o << | ] = col[o];
col[o] = ;
return;
} void add(int p, int l, int r, int o) {
if(l == r) {
sum[o] = ;
return;
}
int mid = (l + r) >> ;
if(p <= mid) add(p, l, mid, o << );
else add(p, mid + , r, o << | );
sum[o] = sum[o << ] + sum[o << | ];
return;
} int getSum(int L, int R, int l, int r, int o) {
if(L <= l && r <= R) return sum[o];
int mid = (l + r) >> , ans = ;
if(L <= mid) ans += getSum(L, R, l, mid, o << );
if(mid < R) ans += getSum(L, R, mid + , r, o << | );
return ans;
} void change(int L, int R, int v, int l, int r, int o) {
if(L <= l && r <= R) {
col[o] = v;
return;
}
pushdown(o);
int mid = (l + r) >> ;
if(L <= mid) change(L, R, v, l, mid, o << );
if(mid < R) change(L, R, v, mid + , r, o << | );
return;
} int ask(int p, int l, int r, int o) {
if(l == r) return col[o];
int mid = (l + r) >> ;
pushdown(o);
if(p <= mid) return ask(p, l, mid, o << );
else return ask(p, mid + , r, o << | );
} int getKth(int k, int l, int r, int o) {
if(l == r) {
return r + (k > sum[o]);
}
int mid = (l + r) >> ;
if(k <= sum[o << ]) {
return getKth(k, l, mid, o << );
}
else {
return getKth(k - sum[o << ], mid + , r, o << | );
}
} int main() { int n;
scanf("%d", &n);
for(int i = ; i <= n; i++) {
scanf("%d", &d[i]);
pos[d[i]] = i;
}
for(int i = ; i <= n; i++) {
scanf("%d", &b[i]);
}
/// h[1] = 1
for(int i = ; i <= n; i++) {
/// b[i] in pos[b[i]]
int p = pos[b[i]], lastp = pos[b[i - ]];
add(p, , n, );
int s = getSum(, p, , n, );
int ed = getKth(s + , , n, ) - ;
/// [p, ed]
if(i == ) {
h[b[i]] = ;
}
else if(p == lastp + && s == p && (ed < n ? getSum(ed + , n, , n, ) : ) == n - ed) {
int fr = ask(p, , n, );
if(fr != d[]) h[b[i]] = (h[fr] + + h[b[i - ]]) / ;
else h[b[i]] = h[fr] + ;
}
else if(p < lastp) { /// new line
int fr = ask(p, , n, );
h[b[i]] = h[fr] + ;
}
else {
h[b[i]] = h[b[i - ]];
}
change(p, ed, b[i], , n, );
} printf("%.3f\n", h[b[n]]);
return ;
}

AC代码

LOJ#2665 树的计数的更多相关文章

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

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

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

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

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

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

  4. BZOJ1211: [HNOI2004]树的计数

    1211: [HNOI2004]树的计数 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1245  Solved: 383[Submit][Statu ...

  5. BZOJ 1211: [HNOI2004]树的计数( 组合数学 )

    知道prufer序列就能写...就是求个可重集的排列...先判掉奇怪的情况, 然后答案是(N-2)!/π(d[i]-1)! -------------------------------------- ...

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

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

  7. 【BZOJ 1211】 1211: [HNOI2004]树的计数 (prufer序列、计数)

    1211: [HNOI2004]树的计数 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2468  Solved: 868 Description 一 ...

  8. bzoj1211: [HNOI2004]树的计数 prufer编码

    题目链接 bzoj1211: [HNOI2004]树的计数 题解 prufer序 可重排列计数 代码 #include<bits/stdc++.h> using namespace std ...

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

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

随机推荐

  1. java--基本数据类型的转换(自动转换)

    概念:Java中,经常可以遇到类型转换的场景,从变量的定义到复制.数值变量的计算到方法的参数传递.基类与派生类间的造型等,随处可见类型转换的身影.Java中的类型转换在Java编码中具有重要的作用.首 ...

  2. pycharm中Django的安装和简单使用

    一.安装: 1.点击File,找到setting选项 2.点击+号,进入下面界面 结束后,安装完成 二.创建Django项目 创建成功后,新项目左侧: templates:用于存储HTML文件 set ...

  3. 第三次上机,ADO接口的使用

    <html> <head> <title>Reg</title> </head> <body><center> &l ...

  4. ubuntu server 16.04 开启root密码登录

    0x00 ubuntu server 16.04 开启root密码登录 由于众多VPS默认使用证书验证登录,虽然安全但使用十分不便,所以特提供开启root用户并使用密码登录方法. 0x01 为root ...

  5. 超级有爱的五款APP共享 可以让你神操作

    随着科技的不断发展,手机功能的不断完善,让我们更加依赖手机,不得不说手机给我们带来很多的乐趣和方便. 今天就主要给大家分享五款超级有爱的APP软件,感兴趣的小伙伴已经迫不及待了吧! 荔枝 荔枝是一款声 ...

  6. arcgis api 3.x for js 入门开发系列十六迁徙流动图

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  7. vivo7.0以上系统如何无需Root激活Xposed框架的方法

    在较多公司的引流或者业务操作中,基本都需要使用安卓的黑高科技术Xposed框架,几天前我们公司购买了一批新的vivo7.0以上系统,基本都都是基于7.0以上版本,基本都不能够获取Root的su超级权限 ...

  8. SQL Server数据库————模糊查询和聚合函数

    ***********模糊查询*********/ 关键字: like (!!!!字符串类型) in (,,)  匹配()内的某个具体值(括号里可以写多个值) between... and.. 在某两 ...

  9. k8s 集群部署问题整理

    1.hostname “master” could not be reached在host中没有加解析 2.curl -sSL http://localhost:10248/healthzcurl: ...

  10. ztree搜索节点并展开

    web <div class="zTreeC"> <div class="searchL" lay-filter="searchL& ...