【树链剖分】链剖相关总结与心得

这两天连着做了一些链剖也看了不少链剖已经大致明白链剖里题目特点了

链剖题目分类

我们可以把所有链剖的题目分为如下两类:

给定点权的链剖

这类链剖也是最基础的链剖,大部分题目都是这个样子的.

题目中会给定每一个点的初始点权,以此来计算路径长度.

这种题目相对来说比较简单,我们直接套模板两次DFS然后建树,把每个点在线段树上对应节点的数值modify就好了.

标准模板题可以看:ZJOI2008树的统计Count

那就是一个裸的点权链剖

给定边权的链剖

这类链剖相比上面那个会稍微复杂一点.

题目中给定树的边权.

对于这种问题,做法很多,我的做法是在每条边的两个端点中,取深度较大的那一个,将其点权记录为边权.最后我们有了所有点的点权(其中1号点的点权为1)然后就可以转化成第一种问题来计算.

需要注意的是,由于我们采用这种方式所以需要对原本点权链剖的query函数略加改进,也就是我们在查询最大值时不能直接查询到最近公共祖先而是要查询到祖先下面的某个点.

模板题比如SPOJ QTREE

关于链剖的写法

我已经见过了两种链剖,他们的区别主要就在于父亲节点的记录方式即fa数组.

网上广为流传的一种链剖是fa函数只开一维,只记录其直接父节点(好像是这个样子我没仔细研究过毕竟不写那种)

另一种链剖是蒋一瑶神犇开创的,该种链剖父亲节点使用倍增方式记录,fa[MAXN][18]即这个样子.由于hzwer神犇也是写的这种链剖,我当时也是跟他学的这种链剖.

链剖与LCT的比较

网上普遍认为的是LCT绝大部分时候可以完全代替链剖.

二者的复杂度分别是O(Q log n)(LCT)和O(Q log2n)(链剖).后面的差别在于前者是借助Splay维护后者是借助线段树维护而且LCT可以实现添边删边等操作.

不过根据zky学长说的,LCT相比链剖常数比较大,因此复杂度的差别有时候并不是很明显.(想喷这句话的请注意”有的时候”)

而且显然LCT要比链剖难写多了(至少我是这么认为的)

尽管LCT大部分时候可以虐链剖,但是用链剖来骗骗分还是很好的选择嘛╮(╯▽╰)╭

不过链剖还是真特么难调啊…毕竟带高级数据结构的东西都很难调都很蛋疼QAQ

更主要的是我太沙茶了2333

大概就是这些了www

月下毛景树还真是蛋疼调啊调调不出来QAQ

原文地址:http://blog.csdn.net/creationaugust/article/details/44261593

时间: 2024-08-03 08:33:10

【树链剖分】链剖相关总结与心得的相关文章

[POJ3237]Tree解题报告|树链剖分|边剖

关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a

树分治&树链剖分相关题目讨论

预备知识 树分治,树链剖分   poj1741 ?一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs.com/chouti/p/5836926.html   OrzFang Ⅸ ?有一棵n个点,边长为1的树,他要在树上选择一个大小为m的点集,使得这m个点两两距离相等. 方方方想知道这么做的方案数对998244353取模后的结果. 题解 首先肯定有一个中心点,使得这个点到m个点距离相等 那么枚举这个

树链剖分小结

这两周在学树剖. 先扔个模板 有一类题目,要求实现一类在树上的操作,比如: 修改/求 树上某 节点/边权 的(最)值: 修改/求 树上某 节点/边权 及其子树上所有节点的(最)值: 修改/求 树上某两点路径间的 节点/边权 的(最)值: 乍一看似乎用线段树就可以实现,但是如果仔细想想,可以发现单凭线段树是无法解决的. 对于这类题目,常用的解决方法是树链剖分. 树链剖分(节选自starszys博客): 相关定义: 重儿子:siz[u]为v的子节点中siz值最大的,那么u就是v的重儿子. 轻儿子:v

树链剖分总结

转载自zzq巨佬的树链剖分: http://blog.csdn.net/Love_mona/article/details/79344296 蒟蒻的垂死挣扎 (以洛谷上树链剖分模板为题来介绍:[洛谷P3384] [模板]树链剖分) 听说树剖很简单 树剖大概算一种思想吧,通过一种巧妙的方式把一棵树的节点有序地排在一个一维数组里,使得其相关询问可以通过线段树等数据结构来维护. 那么难点就在这了,这个巧妙的方法到底是什么呢? 首先引入几个概念: 重结点:子树结点数目最多的结点: 轻节点:父亲节点中除了

【Luogu P3384】树链剖分模板

树链剖分的基本思想是把一棵树剖分成若干条链,再利用线段树等数据结构维护相关数据,可以非常暴力优雅地解决很多问题. 树链剖分中的几个基本概念: 重儿子:对于当前节点的所有儿子中,子树大小最大的一个儿子就是重儿子(子树大小相同的则随意取一个) 轻儿子:不是重儿子就是轻儿子 重边:连接父节点和重儿子的边 轻边:连接父节点和轻儿子的边 重链:相邻重边相连形成的链 值得注意的还有以下几点: 叶子节点没有重儿子也没有轻儿子: 对于每一条重链,其起点必然是轻儿子: 单独一个轻叶子节点也是一条重链: 结合上面三

bzoj3694: 最短路(树链剖分/并查集)

bzoj1576的帮我们跑好最短路版本23333(双倍经验!嘿嘿嘿 这题可以用树链剖分或并查集写.树链剖分非常显然,并查集的写法比较妙,涨了个姿势,原来并查集的路径压缩还能这么用... 首先对于不在最短路径树上的边x->y,设t为最短路径树上lca(x,y),则t到y上的路径上的点i到根的距离都可以用h[x]+dis[x][y]+h[y]-h[i](h[]为深度)来更新,因为h[i]一定,只要让h[x]+dis[x][y]+h[y]最小就行,这里用树剖直接修改整条链上的数,就可以过了. 并查集的

树链剖分专题

学习了一下树链剖分,找了几个有意义的题目训练一下 前4题是基础训练, A.B是AOV树(点记录信息) C.D是AOE树(边记录信息) *注意一下poj好像是提交的代码包含/**/这样的注释会出问题 A.HDU 3966 题意:给你N个点M条边的一棵AOV树,有P次操作 操作分别是:‘I’:将C1到C2路径上的点增加K:     ‘D’:将C1到C2路径上的点减少K:     ‘Q’:问你C点上的权: 解:树链剖分基础题,需要注意的是杭电的服务器是windows的,代码中加入用下面这句话扩栈 #p

[bzoj 2243]: [SDOI2011]染色 [树链剖分][线段树]

Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写一个程序依次完成这m个操作. Input 第一行包含2个整数n和m,分别表示节点数和操作数: 第二行包含n个正整数表示n个节点的初始颜色 下面 行每行包含两个整数x和y,表示x和y之间有一条无向边. 下面 行每行描述一个操作: “C a

【模板】树链剖分

树链剖分是一种应付树上修改和查询的算法(数据结构),要求树的形态不发生改变(改变的要用LCT维护) 树剖可以解决如下问题:路径修改(查询),子树修改(查询),单点修改. 其实有的题目DFS序即可,还有的要用点分治会明显方便一些. 本模板支持:输入p,q,查询p,q的路径上的权值和,给定p,w,将p子树权值增加w,单点增加权值(其实怎么搞都好,只要树的形态不改变,修改满足线段树要求) 1 #include<stdio.h> 2 #define maxn 1000 3 struct node{in