DFS序详解
dfs序就是一棵树在dfs遍历时组成的节点序列.
它有这样一个特点:一棵子树的dfs序是一个区间.
下面是dfs序的基本代码:
void dfs(int x,int pre,int d){//L,R表示一个子树的范围
L[x]=++tot;
dep[x]=d;
for(int i=;i<e[x].size();i++){
int y=e[x][i];
if(y==pre)continue;
dfs(y,x,d+);
}
R[x]=tot;
}
给定一颗树, 和每个节点的权值.下面有7个经典的关于dfs序的问题:
1. 对某个节点X权值加上一个数W, 查询某个子树X里所有点权的和.
由于X的子树在DFS序中是连续的一段, 只需要维护一个dfs序列,用树状数组实现:单点修改和区间查询.
2. 对节点X到Y的最短路上所有点权都加一个数W, 查询某个点的权值.
这个操作等价于a. 对X到根节点路径上所有点权加W
b. 对Y到根节点路径上所有点权加W
c. 对LCA(x, y)到根节点路径上所有点权值减W
d. 对LCA(x,y)的父节点 fa(LCA(x, y))到根节点路径上所有权值减W
于是要进行四次这样从一个点到根节点的区间修改.将问题进一步简化, 进行一个点X到根节点的区间修改, 查询其他一点Y时,只有X在Y的子树内, X对Y的值才有贡献且贡献值为W.当单点更新X时,X实现了对X到根的路径上所有点贡献了W.于是只需要更新四个点(单点更新) ,查询一个点的子树内所有点权的和(区间求和)即可.
3. 对节点X到Y的最短路上所有点权都加一个数W, 查询某个点子树的权值之和.
同问题2中的修改方法, 转化为修改某点到根节点的权值加/减W
当修改某个节点A, 查询另一节点B时
只有A在B的子树内, Y的值会增加
W * (dep[A] - dep[B] + 1) => W * (dep [A] + 1) - W * dep[B]
那么我们处理两个数组就可以实现:
处理出数组Sum1,每次更新W*(dep[A]+1),和数组Sum2,每次更新W.
每次查询结果为Sum1(R[B]) – Sum1(L[B]-1) - (Sum2(R[B]) – Sum2(L[B]-1)) * dep [B].
4. 对某个点X权值加上一个数W, 查询X到Y路径上所有点权之和.
求X到Y路径上所有的点权之和, 和前面X到Y路径上所有点权加一个数相似
这个问题转化为
X到根节点的和 + Y到根节点的和 - LCA(x, y)到根节点的和 - fa(LCA(x,y)) 到根节点的和
更新某个点x的权值时,只会对它的子树产生影响,对x的子树的每个点到根的距离都加了W.
那么我们用”刷漆”(差分前缀和),更新一个子树的权值.给L[x]加上W,给R[x]+1减去W,那么sum(1~L[k])就是k到根的路径点权和.
5. 对节点X的子树所有节点加上一个值W, 查询X到Y的路径上所有点的权值和
同问题4把路径上求和转化为四个点到根节点的和
X到根节点的和 + Y到根节点的和 - LCA(x, y)到根节点的和 - parent(LCA(x,y)) 到根节点的
再用刷漆只更新子树.
修改一点A, 查询某点B到根节点时, 只有B在A的子树内, A对B才有贡献.
贡献为W * (dep[B] - dep[A] + 1) => W * (1 - dep[A]) + W * dep[B]
和第三题一样, 用两个sum1,sum2维护 W *(dep[A] + 1),和W.
最后答案就是sum2*dep[B]-sum1.
6. 对子树X里所有节点加上一个值W, 查询某个点的值.
对DFS序来说, 子树内所有节点加W, 就是一段区间加W.
所以这个问题就是 区间修改, 单点查询.树状数组+刷漆.
7.对子树X里所有节点加上一个值W, 查询某个子树的权值和.
子树所有节点加W, 就是某段区间加W, 查询某个子树的权值和, 就是查询某段区间的和
区间修改区间求和,用线段树可以很好解决.
DFS序详解的更多相关文章
- JS-排序详解:冒泡排序、选择排序和快速排序
JS-排序详解-冒泡排序 说明 时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 不稳定指,如果a=b,a在 ...
- JS-排序详解-冒泡排序
说明 时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 不稳定指,如果a=b,a在b的前面,排序后可能会交换 ...
- JS-排序详解-选择排序
说明 时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 不稳定指,如果a=b,a在b的前面,排序后可能会交换 ...
- JS-排序详解-快速排序
说明 时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 不稳定指,如果a=b,a在b的前面,排序后可能会交换 ...
- Hadoop(四)HDFS集群详解
前言 前面几篇简单介绍了什么是大数据和Hadoop,也说了怎么搭建最简单的伪分布式和全分布式的hadoop集群.接下来这篇我详细的分享一下HDFS. HDFS前言: 设计思想:(分而治之)将大文件.大 ...
- adoop(四)HDFS集群详解
阅读目录(Content) 一.HDFS概述 1.1.HDFS概述 1.2.HDFS的概念和特性 1.3.HDFS的局限性 1.4.HDFS保证可靠性的措施 二.HDFS基本概念 2.1.HDFS主从 ...
- dfs序+RMQ求LCA详解
首先安利自己倍增求LCA的博客,前置(算不上)知识在此. LCA有3种求法:倍增求lca(上面qwq),树链剖分求lca(什么时候会了树链剖分再说.),还有,标题. 是的你也来和我一起学习这个了qwq ...
- 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)
参考网址:图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) - 51CTO.COM 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath ...
- 【转】logback 常用配置详解(序)logback 简介
原创文章,转载请指明出处:http://aub.iteye.com/blog/1101222, 尊重他人即尊重自己 详细整理了logback常用配置, 不是官网手册的翻译版,而是使用总结,旨在更快更透 ...
随机推荐
- php文件上传参考配置与大文件上传
PHP用超级全局变量数组$_FILES来记录文件上传相关信息的,在php文件上传之前,可通过调节php.ini中相关配置指令,来控制上传相关细节. 1.file_uploads=on/off ...
- C++ 基础算法之二分查找
前提: 有序数组! int binary_search(int* a, int len, int goal) { ; ; while(low <= high) { ; if(a[middle] ...
- jQuery初级篇(一)
知识说明: jQuery库是一个javascript库文件,它比起javascript来,写的更少,但做得更多,下面便对刚开始学习jQuery,一些基础知识整理出来,供后期翻阅. 一. jQ ...
- Command Pattern
当(客户)对象访问(服务)请求服务时,最直接的方法就是方法调用.
- JavaScript控制类名(className属性)
语法:object.className =classname (注意大小写) 作用:获取元素的class属性,为网页内的某个元素指定一个CSS样式来更改该元素的外观 示例: <!DOCTYP ...
- css中clearfix清除浮动的用法及其原理示例介绍
clearfix的定义: .clearfix:after {}{ content: "."; /**//*内容为“.”就是一个英文的句号而已.也可以不写.*/ display: b ...
- ObjC宏定义小细节
Macros A definition that takes arguments, particularly more than one, is often known as a macro: #de ...
- CMD的几个常用API
一: define, 全局函数,用来定义模块. 参数: 1.id 模块标识(可省略) 2.deps模块依赖(比如jquery)(可省略) 3.factory:可能是: (1)对象 (2)字符串 ①和 ...
- iis express 局域网访问
查找到配置文件添加一条绑定局域网可访问的IP地址即可: 事例: <site name="Join.Lims.Mob(11)" id="19"> &l ...
- Python学习之变量
Python 变量 python不用事先声明变量,赋值过程中就包含了变量声明和定义的过程 用“=”赋值,左边是变量名,右边是变量的值 数字 整数 int_var = 1 长整数 long_var = ...