首页 > 其他分享 >树链剖分

树链剖分

时间:2024-04-24 21:45:45浏览次数:19  
标签:dep 剖分 int top son fa 树链 size

参考链接:https://www.cnblogs.com/dx123/p/16320467.html(感谢董晓老师)

树链剖分求LCA

比倍增快一些
https://www.luogu.com.cn/problem/P3379

#include<bits/stdc++.h>
const int N = 5e5 + 5;
using namespace std;
int n,m,root; 
int h[N],ne[2 * N],e[2 * N],idx;
int dep[N],size[N],son[N],top[N],fa[N];
void add(int a,int b){
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx++;
}
void dfs1(int u){
	size[u] = 1;
	dep[u] = dep[fa[u]] + 1;
	for(int i = h[u];~i;i = ne[i]){
		int v = e[i];
		if(v == fa[u]) continue;
		fa[v] = u;
		dfs1(v);
		size[u] += size[v];
		if(!son[u] || size[son[u]] < size[v]) son[u] = v; 
	} 
}
void dfs2(int u,int ttop){
	top[u] = ttop;
	if(son[u]) dfs2(son[u],ttop);
	for(int i = h[u];~i;i = ne[i]){
		int v = e[i];
		if(v == fa[u] || v == son[u]) continue;
		dfs2(v,v);
	}
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> n >> m >> root;
	memset(h,-1,sizeof(h));
	for(int i = 1;i <= n - 1;++i){
		int a,b; cin >> a >> b;
		add(a,b);add(b,a);
	} 
	dfs1(root);
	dfs2(root,root);
	for(int i = 1;i <= m;++i){
		int u,v; cin >> u >> v;
		while(top[u] != top[v]){
			if(dep[top[u]] >= dep[top[v]]) u = fa[top[u]];
			else                           v = fa[top[v]];
		} 
		if(dep[u] < dep[v]) cout << u << '\n';
		else                cout << v << '\n';
	}
	return 0;
} 

标签:dep,剖分,int,top,son,fa,树链,size
From: https://www.cnblogs.com/gebeng/p/18156420

相关文章

  • 树链剖分lca笔记
    树链剖分求lca参考资料:https://www.cnblogs.com/cangT-Tlan/p/8846408.html[树链剖分lca]大佬讲的很清楚%%%orz这篇博客是我的学习笔记。树链剖分:树链剖分,计算机术语,指一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链,保证每个点属于且只属于一条链,然后再通过数据结......
  • 「树链剖分」 学习笔记
    一,树链剖分的思想与概述正如其名,树链剖分用于将树剖分成若干条链的形式,以维护树上路径的信息,其中剖分出的链有多种形式,最常见的是重链,还有长链或更多其它的链。其中剖分出的链为重链时,就引出了下文的主角「重链剖分」。重链剖分能保证划分出的每条重链上的节点DFS序连续,因此......
  • 树链剖分 学习笔记
    随便写一点。1.原理定义重儿子为子树内子树大小最大的任一个点,重边为重儿子向其父亲连的边,其余为轻边。根据定义,轻边的父亲的子树大小一定不小于这个点的子树大小的二倍。又可以证出重边数量是\(O(\logn)\)的。因此可以用线段树维护这个东西。2.应用2.1dsu2.2lca考......
  • 【学习笔记】树链剖分
    一、重链剖分1.定义&作用树链剖分用于解决在树上执行的操作,将树上操作变为区间操作。用区间来维护。2.主要思想&实现有一棵树然后,我们把边区分一下,有一些边是“重边”,其余的是“轻边”,像这样:(红边为重边,黑边为轻)重边和轻边如何确定呢?看每一个结点旁的红色数字,代表他......
  • 1039. 多边形三角剖分的最低得分
    题目链接:实现一、记忆化搜索classSolution{public:intminScoreTriangulation(vector<int>&values){intn=values.size();intmemo[n][n];memset(memo,-1,sizeofmemo);//-1表示还没有计算过function<int(int,int)>df......
  • 重链剖分学习笔记
    Part.1引入重链剖分是一种用于解决树上的路径查询和修改问题的算法,他能将\(O(n)\)级别的操作转换为\(O(\logn)\)的级别,可以说十分常用。本文将带你深入解析这个算法。Part.2概念和思路在讲解本算法之前,我们先引入一些概念:轻重儿子:对于一个树上的节点\(u\),其儿子中子......
  • 树链剖分
    前言打算好好写一篇文章。至于为什么选了树剖这个主题,一是因为不久前学了长剖求树上k级祖先,二是因为重剖是我进提前批以来第一个学习到的树上算法,再加上有学弟写的超级详细的树剖学习笔记,也会使我写起来比较轻松一点。同时也可以熟悉一下TikZ这个宏包,它的功能实在是太多了,......
  • P8025 【树链剖分求祖先】
    P8025【树链剖分求祖先】这题的题意简单,简单分类讨论一下这里就不赘述了。最后题目就简化成求一个点的\(k\)级祖先。开始会的解法是倍增,但是常数过高被卡了。常数更优秀的做法是树剖,每一次跳树链,最后可能有一条链太长只能跳一部分,这是因为树链剖分的\(dfn\)序是有序的,即每......
  • P3384 【模板】重链剖分/树链剖分
    原题链接题解dalao‘sblog我自己的认识请看代码区code#include<bits/stdc++.h>usingnamespacestd;intn,Q,root,mod;intbigson[100005];//和自己在同一条链上的儿子节点vector<int>G[100005];intsizes[100005];//主要是为了求子树大小,经过验证选择哪一个儿子节点......
  • 树链剖分
    重链剖分【模板】重链剖分/树链剖分upd:每条重链必定由轻儿子开始,不同重链间必定由轻边连接,重链之内必定是重边。如果只有一次询问的话显然可以树上差分来解决,现在考虑多组询问。处理fa[i]dep[i]便于询问。处理size[i]son[i]top[i]idx[i]f[i]便于树剖。明确一下树剖......