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常用配置, 不是官网手册的翻译版,而是使用总结,旨在更快更透 ...
随机推荐
- 进程间通信--fork函数
#include <unistd.h> pid_t fork(void); fork() creates a new process by duplicating the calling ...
- javafx之HTTP协议交互
javafx端要获取获取如下信息: 服务器端获取的数据: javafx客户端发送的数据以及获取的数据: 工程目录: package Httputil; import IPsite.IPaddress; ...
- Maven 常用的命令
运行几个基本的Maven命令 mvn compile 编译主程序 mvn test-compile 编译测试程序 mvn clean 清理 mvn test 测试 mvn pac ...
- Android在外部存储空间中读写文件
一.外部存储的目录 1.2.3之前是/sdcard 2.4.3之前是在/mnt/sdcard 3.4.3之后是在/storage/sdcard 二.读写读写外部存储 1.直接写路径 File file ...
- ACM_1001_Exponentiation 详解
参考:http://blog.csdn.net/rually/article/details/8585268 #include<iostream> using namespace std; ...
- mysqlnd cannot connect 连接错误处理方法
mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. Please use an administra ...
- [解决方案] pythonchallenge level 2
http://www.pythonchallenge.com/pc/def/ocr.html 根据页面提示查看网页源代码,在最后:<!--find rare characters in the ...
- 使用Mybatis-Generator自动生成Dao、Model、Mapping代码
1.所需jar包 mybatis-generator-core-1.3.2.jar mybatis-generator-core-1.3.2.jar 可以去http://mvnrepository.c ...
- linux命令:tar
1.命令介绍: tar用来打包,压缩和解压文件. 2.命令格式: tar [选项] 文件 3.命令参数: 必要参数有如下: -A 新增压缩文件到已存在的压缩 -B 设置区块大小 -c 建立新的压缩文件 ...
- git 较基础命令
还需要进一步了解git的组织形式: git clone *.git 下载下来以git方式管理 如果直接下载压缩包做不到 git branch 分支相关命令 git checkout 可以换分支 git ...