LOJ#2665 树的计数
题意:给你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 树的计数的更多相关文章
- loj#2665. 「NOI2013」树的计数
目录 题目链接 题解 代码 题目链接 loj#2665. 「NOI2013」树的计数 题解 求树高的期望 对bfs序分层 考虑同时符合dfs和bfs序的树满足什么条件 第一个点要强制分层 对于bfs序 ...
- 树的计数 + prufer序列与Cayley公式 学习笔记
首先是 Martrix67 的博文:http://www.matrix67.com/blog/archives/682 然后是morejarphone同学的博文:http://blog.csdn.ne ...
- 【BZOJ】【1211】【HNOI2004】树的计数
Prufer序列+组合数学 嗯哼~给定每个点的度数!求树的种数!那么很自然的就想到是用prufer序列啦~(不知道prufer序列的……自己再找找资料吧,这里就不放了,可以去做一下BZOJ1005明明 ...
- BZOJ1211: [HNOI2004]树的计数
1211: [HNOI2004]树的计数 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1245 Solved: 383[Submit][Statu ...
- BZOJ 1211: [HNOI2004]树的计数( 组合数学 )
知道prufer序列就能写...就是求个可重集的排列...先判掉奇怪的情况, 然后答案是(N-2)!/π(d[i]-1)! -------------------------------------- ...
- 「NOI2013」树的计数 解题报告
「NOI2013」树的计数 这什么神题 考虑对bfs重新编号为1,2,3...n,然后重新搞一下dfs序 设dfs序为\(dfn_i\),dfs序第\(i\)位对应的节点为\(pos_i\) 一个暴力 ...
- 【BZOJ 1211】 1211: [HNOI2004]树的计数 (prufer序列、计数)
1211: [HNOI2004]树的计数 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2468 Solved: 868 Description 一 ...
- bzoj1211: [HNOI2004]树的计数 prufer编码
题目链接 bzoj1211: [HNOI2004]树的计数 题解 prufer序 可重排列计数 代码 #include<bits/stdc++.h> using namespace std ...
- UOJ #122 【NOI2013】 树的计数
题目链接:树的计数 这道题好神啊……正好有人讲了这道题,那么我就写掉吧…… 首先,为了方便考虑,我们可以把节点重标号,使得\(bfs\)序变成\(1,2,3,\dots,n\),那么显然树的深度就是\ ...
随机推荐
- 《全栈营销之如何制作个人博客》之二:php环境安装及个人博客后台搭建 让你的博客跑起来
上一节我们讲了个人博客用什么开发语言,用什么CMS系统,从这一节我们就开始真正的干货,这一节我们讨论一下PHP环境的安装,及个人博客后台的搭建,让你的博客在正常的PHP环境中运行起来,你就可以进行后台 ...
- js字符串转json格式与json对象转字符串
json字符串----->json对象json对象------>json字符串 使用JSON.parse()函数 this.dataList = JSON.parse(dataList); ...
- [转载]编写SQL语句查询出每个各科班分数最高的同学的名字,班级名称,课程名称,分数
[转载]编写SQL语句查询出每个各科班分数最高的同学的名字,班级名称,课程名称,分数 转载自:https://blog.csdn.net/one_money/article/details/56921 ...
- Flutter项目之app升级方案
题接上篇的文章的项目,还是那个空货管理app.本篇文章用于讲解基于Flutter的app项目的升级方案. 在我接触Flutter之前,做过一个比较失败的基于DCloud的HTML5+技术的app,做过 ...
- java:数据结构(二)栈的应用(进制转换全收集)
说到进制转换,java已经封装了基本的方法,在竞赛中使用封装的方法自然能节省大量时间 另一位仁兄介绍的封装好的方法: https://blog.csdn.net/m0_37961948/article ...
- 关于写作那些事之利用 js 统计各大博客阅读量
在日常文章数据统计的过程中,纯手动方式已经难以应付,于是乎,逐步开始了程序介入方式进行统计. 在上一节中,探索利用 csv 文件格式进行文章数据统计,本来以为能够应付一阵子,没想到仅仅一天我就放弃了. ...
- Jmeter Beanshell 用法
Beanshell 的用法 什么是beanshell Beanshell是一种完全符合java语法的脚本语言,并且拥有自己的内置对象和语法 Beanshell是用java写的,一个小型嵌入式java源 ...
- 应用shell脚本停启Tomcat
最近在工作中频繁的操作多个tomcat,顺便就简单研究了一下 一. 简介 Shell 是一种与操作系统直接交互的程序,Unix系统中叫Bourne Shell,包括以下几种 Sh—Bourne She ...
- 点击 Button触发事件将GridView1 CheckBox勾选的行添加到GridView2中
有时候想实现一个CheckBox选取功能,但是很多细节不是很清楚 相信大家都有遇到类似的情况,直接看代码,如下: 前端代码GridView1,CheckBox控件设置 <asp:GridView ...
- java jdk动态代理(proxy)
1. 涉及主要jdk api java.lang.reflect.InvocationHandler: public interface InvocationHandler { /** * Proce ...