树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询
思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几条链 那么就是对一群区间进行更改 这时候基本是用线段树进行logn的操作
做了三道基础题 都属于比较好想的 也就是线段树比较麻烦 需要写相当长一段时间...
HDU 3966
给出一棵树的连接状况和边的大小 每次可以对a-b的路径的边的权值取反 或者改变指定边的值 或者求a-b路径的最大值
每次取反 最大值就是原最小值*-1 这样维护下去就好
POJ 3237
给出一棵树的连接状况和点的初始值 每次对a-b的路径上的点权进行加减 询问单点大小
树状数组会超时 只能用线段树...需要注意的是点权和边权在树链剖分的时候会有一点不同 例如 u == v 是否return 等
HYSBZ 2243
总觉得以前见过的样子..
给出一棵树的连接状况和边的初始颜色 每次可以对a-b的路径上的边进行更改颜色
最后求a-b路径上的颜色段个数
可以由线段树的本质来看 每个区间的两个子区间 都是从这个线段树一分为2
那么 一个区间内有多少个颜色段数 就等于他的两个子区间的颜色加起来 如果子区间相邻的点颜色相同 那么久减去一
可以在tr数组中记录这个区间的mlmr 即中点两边的点的颜色
每次记录下来前一条链的尾颜色 和当前链的头颜色进行对比 如果相同 就减一
最后当f1 == f2的时候 要同时对比ys1和ys2
交换uv的时候 ys1和ys2也需要交换
#include #include #include #include #include
感觉树链剖分的主要难点在于线段树的构造...
2017.3.18 很久后又做了一道树链剖分 当然LCA也可做
询问树上路径可否组成三角形 利用斐波那契的思想 由于每一条路径的len<=1e9 所以当路径的条数超过64左右的时候肯定是可以的
当小于64的时候拿出来直接暴力就可以了
树链剖分中 u与top[u] 是连着的 在这里 用a[u]存放 u到fa[u] 的边的权值
所以top[u] -> fa[top[u]] 其实是不在 u -> f1 这条链上的 但是之后会发生 u = fa[f1] 直接翻到这条边上去
所以如果top[u] -> fa[top[u]] 这个边不在路径中 是会直接发生 f1 == f2 的
所以这样记录是不会出现什么问题的 QAQ
好久不写 好麻烦...Orz
#include #include #include #include #include