【算法复习】 树链剖分
来源:互联网 发布:数据分析师市场需求 编辑:程序博客网 时间:2024/06/03 16:19
NOIP快到了,本蒟蒻太菜了,今天复习一下树链剖分。
暑假学习了一发树链剖分,打了几题模板题之后就没打了。
一些概念(下面代码会用到):
Son[u]:u结点的重儿子
Size[u]:以u为结点的子树的大小
fa[u]:u结点的父亲
top[u]:该重链的链顶
Num[u]:剖分后的结点编号
Deep[u]:u结点的深度
第一步(Dfs1):找到每个节点的重儿子(子树结点数最大的儿子),同时记录每个结点的深度,父亲,子树大小等必要信息
void Dfs1(int u) //找重儿子 {Size[u]=1;for (int i=head[k];i;i=E[i].next){ int v=E[i].to; if (v==fa[u]) continue; fa[v]=u; Deep[v]=Deep[v]+1; Dfs1(v); Size[u]+=Size[v]; if (Size[v]>Size[Son[u]]) Son[u]=v;}}第二部(Dfs2): 由重儿子打通每一条重链
void Dfs2(int u,int Top)//打通重链{Num[u]=++Index,top[u]=Top;if (!Son[u]) return;Dfs2(Son[u],Top);for (int i=head[u];i;i=E[i].next){ int v=E[i].to; if (v==fa[u] || v=Son[u]) continue; Dfs2(v,v);}}
两个Dfs完了之后,那么一棵树就剖分完成了。(可以手画一棵复杂一点的树理解一下)
然后就会发现一个非常重要的性质:每一条重链上的编号是连续的!!!
接下来就可以用一些其他的数据结构来维护这每一条重链,比如线段树,Splay等等
然而本蒟蒻非常菜,只打过用线段树维护的树链剖分题目
以线段树为例,对于一对结点(u,v),将这两个点不断沿着重链往上爬,边爬边维护重链上的信息,最终这两个点会跳到同一条重链上,这时候在维护一次就好。
void Work(int x,int y){while (top[x]!=top[y])//不在一条重链上 { if (Deep[x]<Deep[y]) swap(x,y);//先跳深度大的点 Modify(1,1,n,Num[top[x]],Num[x]);//线段树修改操作 x=fa[top[x];//跳到该重链链顶的上方,即下一条重链 }//接下来是处理同一条链上的情况 if (Deep[x]<Deep[y]) swap(x,y);Modify(1,1,n,Num[y],Num[x]);}
怎么样,树链剖分是不是很简单。(然而去年不知道自己在干什么居然不会学这个东西)
基本上就是模板了,大致就这样吧,本蒟蒻就只会这些了
阅读全文
0 0
- 【算法复习】 树链剖分
- 算法复习
- 算法复习
- 算法复习
- 算法复习~
- 【算法】生僻算法复习
- 复习:算法复杂度
- 快速排序算法复习
- 排序算法复习
- 复习回溯算法
- 算法复习--插入排序
- 求职复习算法整理
- 回溯算法复习
- 复习 - 算法与数据结构
- 数据结构算法复习
- 排序算法复习笔记
- 简单算法复习
- 算法复习--快速排序
- 战争迷雾制作思路
- 数理逻辑模拟-2
- GhostXP安装时没有D盘问题
- The Matrix
- HTML
- 【算法复习】 树链剖分
- 实现选择功能的那些步骤
- HashMap面试题:90%的人回答不上来
- 表连接,子查询,exists
- Linux学习日志
- Java并发编程: ConcurrentHashMap的锁分段技术
- 笨办法学python习题15 读取文件
- Vim 移动
- JavaScript总结 04