题意:给你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. JVM的总结

    1.JVM的内存模型 JVM主要由程序计数器,虚拟机栈,堆,方法区,本地方法区 1.程序计数器的功能是记录当前线程执行到了字节码文件的哪一行, JVM执行的是.java编译后的.class文件 2.虚 ...

  2. java工作流引擎证照库类型的流程设计 实现方案与演示案例

    关键词:.Net开源工作流    工作流引擎   工作流引擎常用信息存储  流程前置导航 证照库的概念&应用场景: 我们在梳理流程的时候,会发现有一些流程的发起是基于一个实体信息的. 比如:纳 ...

  3. Log4j配置(xml和property两种)

    本文章为转载记录,纯粹个人备忘. 一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR 为严重错误 主要是程序的错误WARN 为一 ...

  4. Jenkins实现简单的CI功能

    步骤一:安装JDK.Tomcat,小儿科的东西不在此详细描述 步骤二:下载安装Jenkins下载链接:https://jenkins.io/download/ 步骤三:将下载的jenkins.war部 ...

  5. Redis 安装总结记录 附送redis-desktop-manager工具

    使用redis已几年有余,之前写过Redis关于master-slave(主从)同步原理的文章.这里介绍下安装过程,因为前前后后有些命令也记不住了,所以此篇文章和之前文章一样起个备注记录作用,也供屏幕 ...

  6. FelxCell常用属性设置(未完待续......)

    this.grid1.AllowUserPaste//返回或设置是否允许用户粘贴文字和格式 grid1.Cell(Rows, 1).WrapText = true;//设置单元格自动换行

  7. RobotFramework第一篇之环境搭建

    定义:是一款python编写的功能自动化测试框架,具备良好的扩展性,可以进行分布性测试 1:对编程能力要求低,容易上手 2:关键字调用方式,已经定义好的功能,只需要去调用它,一个关键字实现了一个功能, ...

  8. python接口自动化-Cookie_绕过验证码登录

    前言 有些登录的接口会有验证码,例如:短信验证码,图形验证码等,这种登录的验证码参数可以从后台获取(或者最直接的可查数据库) 获取不到也没关系,可以通过添加Cookie的方式绕过验证码 前面在“pyt ...

  9. idea右键无法生成javaclass

    博客转自:https://www.cnblogs.com/zjfjava/p/9219237.html 项目中新建目录之后,要在该目录下新增java Class文件,右键——>New发现无对应选 ...

  10. Data Protection - how to manage expired key?(转载)

    问 According to ASP.NET Key Management: Deleting a key is truly destructive behavior, and consequentl ...