树链剖分学习笔记
来源:互联网 发布:粤语翻译普通话软件 编辑:程序博客网 时间:2024/06/05 16:25
时常有一些在树上的问题,朴素的想法时间复杂度很大,于是我们常常会想能不能用什么数据结构把复杂度降下来,但是树的结构又很特殊,所以没有什么好的想法,而树链剖分就是一种很好的手段。
总的来讲树链剖分就是将一棵树剖成许多条链,然后连起来,用数据结构处理的过程,其中要记一些对应关系,方便处理。
首先要处理出重边,所谓重边就是一个节点所有子节点中子树的点数最大的哪个节点与本节点的边。而不是这样的边,就称为轻边。
这样就可以得到两个很重要的性质。
1、轻边(u,v)中,size(v)<=size(u/2)
2、从根到某一点的路径上,不超过logn条轻边和不超过logn条重路径。(这个是计算树链剖分复杂度的核心)
然后剖分的时候就是将树剖成许多重链连接起来,再用数据结构去维护。
剖分的代码主要有两部分
1、找重边
int top[N],dep[N],Rank[N],id[N],son[N],f[N],sz[N];//分别记录这条重链的顶点,每个点的深度,线段树上的这个点对应树上哪个点,树上的点对应线段树上哪个点,重儿子,父亲,子树大小int tot;//最后形成的链长度vector<int> G[N];//邻接表void init(int n){//初始化 tot = 0; memset(son,-1,sizeof(son)); for(int i = 0;i <= n;i++) G[i].clear();}void dfs1(int u,int fa,int d){//求重边 dep[u] = d;//记录深度,父亲 f[u] = fa; sz[u] = 1; for(int i = 0;i < G[u].size();i++){ int v = G[u][i]; if(v == fa) continue; dfs1(v,u,d + 1);//递归子树 sz[u] += sz[v]; if(son[u] == -1 || sz[son[u]] < sz[v]){ son[u] = v;//记录重边 } }}
2、把重边练成链
void dfs2(int u,int tp){//剖分 top[u] = tp;//记录重链顶端的点 id[u] = ++tot;//u在线段树上的地方 Rank[id[u]] = u;//线段树上的地方对应的树上的地方 if(son[u] == -1) return;//没有重儿子,那么肯定是叶子节点 dfs2(son[u],tp);//对重儿子递归 for(int i = 0;i < G[u].size();i++){ int v = G[u][i]; if(v != son[u] && v != f[u])//不是重儿子的重开一条重链 dfs2(v,v); }}
然后之后实现修改的时候(以hdu3966为例)
void change(int x,int y,int val){//将x到y的路径上的值改val while(top[x] != top[y]){//如果不在同一条重链上,就按深度update,然后往同一条重链上靠 if(dep[top[x]] < dep[top[y]]) swap(x,y); update(1,1,n,id[top[x]],id[x],val); x = f[top[x]]; } if(dep[x] > dep[y]) swap(x,y); update(1, 1, n, id[x], id[y],val);}
0 0
- 学习笔记: 树链剖分
- 树链剖分学习笔记
- 树链剖分学习笔记
- 树链剖分学习笔记
- 学习笔记--树链剖分
- 树链剖分学习笔记
- 树链剖分学习笔记
- 树链剖分学习笔记
- 【树链剖分】学习笔记
- 树链剖分学习笔记
- 树链剖分学习笔记
- 树链剖分学习笔记 && SPOJ QTREE
- |算法讨论|树链剖分 学习笔记
- 学习笔记?
- 学习笔记
- 学习笔记
- 学习笔记
- 学习笔记
- 「全栈开发」在就业市场的真正含义
- Appium window环境搭建
- shutdown和closesocket区别
- 日期正则表达式
- poj1050
- 树链剖分学习笔记
- ubuntu开机进入命令行界面与图形界面之间的切换
- 31岁大叔自学android的一点感悟
- Eclipse的working Set里面的东西存储在哪个文件中
- find peak or drop
- python导入自定义模块
- 一个关于SMTP 的封装类
- HttpClient对于https的支持和配置
- mysql入门