总结-树链剖分
来源:互联网 发布:java源代码文件调试 编辑:程序博客网 时间:2024/06/06 03:19
总结-树链剖分
(今天学会了树链剖分,\(^O^)/)
以BZOJ1036为例,题目中要求树上的区间和,最值询问.
若不是在树上的话,很容易想到用线段树来来实现.
树链剖分实质
而树链剖分实际上也就是将树结构剖分成一条一条的链结构,实际上就是区间,以便于数据结构的操作.
就题目而言,若将树剖分成链,那么就很容易再在线段树的基础上维护.
如何剖分?
显然链的条数越少越好,那么对于一个点而言,他只能和其子节点中选择一个分成一条链,其余的另外成链.要使得条数尽可能少,就应当选择节点个数最多的那个子节点,称之为重儿子.其他的轻儿子就另外成链.将节点与其重儿子所形成的边称为重边,其他边称之为轻边.
重链的性质
将全部由重边形成的链称之为重链,可以发现重链和轻边的条数均为
应为对于一个点而言,若其不为父节点的重儿子,那么其子树结点和必定小于等于总结点数的1/2,那么一直出现新的重链只能有
且轻边的条数也是
两点间路径的遍历
很多时候用到树链剖分是在树上操作,那么就可能会涉及到两点间距离操作.
以两点x,y间求区间点权和为例:
1.讨论x,y是否在同一条重链上:
若在,直接用数据结构求[x,y]区间和.
若不在,将所在链顶端较深的向上移动,并记录下该点到所在链顶端的区间和.
代码实现
1.找重边
dfs求出子树结点数,取节点数最大的作为重儿子,得到重儿子之后便知道结点的重边.
int fa[maxn],sz[maxn],son[maxn];//fa 父节点数组 sz 子树结点数 son 结点重儿子void dfs1(int u,int p)//u 当前结点 p 父节点{ sz[u]=1;fa[u]=p;son[u]=0; for(int i=fir[u];i;i=nxt[i]) if(to[i]!=p) { int v=to[i]; dfs1(v,u); sz[u]+=sz[v]; if(sz[v]>sz[son[u]]) son[u]=v; }}
2.成重链
已经求出了重边,现在要将其连起来.既然要连起来,那么重链上的点肯定要连续,那么尝试将同一重链上的点连续存放,形成多个连续区间,那么就将多条重链连起来了.
int top[maxn],dep[maxn],rnk[maxn],idx[maxn],id;//top 结点所在重链的顶端 dep 结点深度 rnk 新标号映射旧标号 idx 旧标号映射新标号void dfs2(int u,int t,int d)//u 当前结点 t 结点所在重链顶端 d 结点深度{ top[u]=t;dep[u]=d;rnk[idx[u]=++id]=u; if(son[u]) dfs2(son[u],t,d+1);//先dfs重儿子,才能保证同重链上的点连续存放 for(int i=fir[u];i;i=nxt[i]) if(to[i]!=fa[u]&&to[i]!=son[u]) dfs2(to[i],to[i],d+1);}
3.两点间路径(以路径点权和为例)
int solve(int x,int y){ int ret=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); ret+=query(1,1,N,idx[top[x]],idx[x],k); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); ret+=query(1,1,N,idx[x],idx[y],k); return ret;}
4.求lca
int lca(int x,int y){ while(top[x]!=top[y]) if(dep[top[x]]>dep[top[y]]) x=fa[top[x]]; else y=fa[top[y]]; return dep[x]<dep[y]?x:y;}
相关题目:
1.BZOJ 1036 题目 题解
2.BZOJ 3637 题目 题解
3.POJ 3237 题目 题解
- 树链剖分总结
- 总结-树链剖分
- 树链剖分总结
- 树链剖分总结
- 树链剖分-总结
- 树链剖分总结
- 树链剖分总结
- 树链剖分个人题目总结
- 【数据结构】树链剖分总结
- 总结
- 总结
- 总结
- 总结
- 总结!
- 总结
- 总结.
- 总结。
- 总结
- java一些细节j
- sql-约束constraint(非空,唯一,主键,外键,检查)自学笔记
- 版本控制工具--Git
- 基本数据类型
- Android基础之startActivityForResult详解
- 总结-树链剖分
- 窗口与winmain-win32与C++入门笔记(2)
- java集合类详解
- canvas中save和restore
- duilib bkimage属性说明
- Android支持多国语言
- 一个简单实用的程序员鸡汤
- android ScrollView嵌套ListView adapter的notifyDataSetChanged无效
- GDAL——生成等值线