首页 > 其他分享 >虚树

虚树

时间:2024-11-11 10:42:38浏览次数:2  
标签:stpos top NG dfn lca st 虚树

建立虚树

先把关键点按\(dfn\)升序排序,单调栈维护树上一条链(\(dfn\)单增),初始为根节点\(1\)

逐个考虑关键点\(x\):

设\(lca=LCA(x,st[top])\),分类讨论:

\(\hspace{0.5cm}\)①若\(lca=st[top]\),表明\(x\)和\(st[]\)同一条链上,直接入栈;

\(\hspace{0.5cm}\)②若\(lca\not=st[top]\),则\(lca\)一定在\(st[top]\)的上方,即子树\(st[top]\)内的关键点已访问完毕,尝试弹出\(st[top]\),继续分类讨论:

\(\hspace{1cm}\)①若\(dfn[lca]>dfn[st[top-1]]\),表明\(lca\)在\(st[top]\)和\(st[top-1]\)中间,将\(lca\)与\(st[top]\)连边,弹出\(st[top]\),再将\(lca\)加入;

\(\hspace{1cm}\)②若\(dfn[lca]\le dfn[st[top-1]]\),表明\(st[top]\)与\(st[top-1]\)直接相连(可以证明没有另外的\(lca'\)在中间),将\(st[top-1]\)与\(st[top]\)连边,弹出\(st[top]\)

结束分类讨论,考虑下一个点

细节

实质上就是个分类讨论:\(lca\)和\(st[top]\)的关系,和\(lca\)和\(st[top-1]\)的关系,像splay一样画个图就想得通了

在加边时建议这样写——先连\(son\to fa\),再补成双边,因为儿子到父亲只有一条边,这时清空$head[]

$最方便,否则要么清多了T掉,要么把刚连上的边清了


void Build2() {

	stpos=NG.tot=NG.head[1]=0;

	st[++stpos]=1;

	for(int i=1,lca;i<=kpos;i++) {

		while((lca=LCA(knod[i],st[stpos]))!=st[stpos]) {

			NG.head[st[stpos]]=0;

			if(dfn[lca]>dfn[st[stpos-1]]) {

				NG.Addedge(st[stpos],lca,Mind(st[stpos],lca));

				st[stpos]=lca;

			}

			else {

				NG.Addedge(st[stpos],st[stpos-1],Mind(st[stpos],st[stpos-1]));

				--stpos;

			}

		}

		st[++stpos]=knod[i];

	}

	while(stpos>1) {

		NG.head[st[stpos]]=0;

		NG.Addedge(st[stpos],st[stpos-1],Mind(st[stpos],st[stpos-1]));

		--stpos;

	}

	for(int i=NG.tot;i;i--) NG.Addedge(NG.e[i].to,NG.e[i].fr,NG.e[i].dis);//,cout<<NG.e[i].to<<' '<<NG.e[i].fr<<' '<<NG.e[i].dis<<endl; 

}

应用

指定贡献点

给出若干组点,每组只有这些点产生贡献

点击查看代码

标签:stpos,top,NG,dfn,lca,st,虚树
From: https://www.cnblogs.com/zhone-lb/p/18539262

相关文章

  • 虚树 学习笔记
    虚树VirtualTree学习笔记引入P2495[SDOI2011]消耗战题目大意:给一棵\(n\)个点的树,\(m\)次询问\(k\)个点,要求切断一些边使点1不可达这些点,求最小切断的边权和。\(n\le2.5*10^5,m\le5*10^5,\sumk\le5*10^5\)先考虑一个朴素的DP,每次询问扫一遍整个树。设\(f_......
  • 虚树
    用以解决树上的和点集相关的问题,将树的大小缩减至\(\mathcal{O}(|S|)\)级别。构建方法即将所有关键点按照\(\rmdfs\)序排序,然后再将\(LCA(s_i,s_{i+1})\)加入并去重,时间复杂度\(\mathcal{O}(n\logn)\)。有线性构建的单调栈方法,没学。粘个代码for(inti=1;i<=k;i++)......
  • 虚树+树形dp
    虚树实际上是一颗浓缩子树;使用虚树的题目大部分具有查询的点有限,同时虚树构建的信息符合规则;做虚树的题目:步骤为先想出原树的暴力求解做法,然后构建虚树同时向其中添加有用信息(比如边权);虚树的构建过程:虚树的构建大致有两种,但是两种方式都与dfs序有关;首先解释为什么与dfs序有......
  • 虚树
    消耗战首先考虑朴素\(dp\),设\(f_u\)表示使\(u\)的子树内的所有关键点都不与\(u\)连通的最小代价。如果当前在\(u\),\(j\)这个儿子是关键点,那么有转移\(f_u\leftarrowf_u+val_{u\rightarrowj}\);否则有转移\(f_u\leftarrowf_u+\min(f_j,val_{u\rightarrowj})\)。这......
  • 虚树总结
    之前学了一些算法,没有写算法总结,未来会陆续补一些。前置知识:树形\(dp\),\(lca\),\(dfs\)序。我们考虑\([HEOI2014]\)大工程这道题。显而易见,假如这道题只有一次询问,我们可以直接树形\(dp\),快速求出答案,时间复杂度\(O(n)\)。但是,梦想是梦想,现实是现实,这题多组询问,假如一......
  • 虚树
    引入$\color{skyblue}P2495[SDOI2011]消耗战$题意给定一颗$n$个节点的树,每条边有边权。有$m$次询问,每次询问钦定$k$个特殊节点,问使得节点$1$不与任何特殊节点相连通所需要删除的最小总边权是多少。数据范围:对于\(100\%\)的数据,\(2\leqn\leq2.5\ti......
  • 虚树
    虚树VirtualTree浓缩信息,把一整颗大树浓缩成一颗小树。下图中,红色结点是我们选择的关键点。红色和黑色结点都是虚树中的点。黑色的边是虚树中的边。OIWIKI两种建树方式1.第一种构造过程:二次排序+LCA连边(容易理解,常数略大)boolcmp(intx,inty){returndfn[x......
  • 关于虚树
    关于虚树瞎扯某些树上问题,给了巨多节点,而实际上它们之中只有小部分能做出贡献,其余都是些水军,为杀尽OIers的脑细胞做出努力考虑重新种一棵树,浓缩信息,简化节点个数,于是产生了虚树。大概是长这个样子:红色结点是我们选择的关键点,即能够做出贡献的点。红色和黑色结点都是虚树中......
  • 20240806:点分治,虚树选做
    POJ-1741Tree题意:给定一棵树,求多少无序对\((u,v)\)满足\(\text{dist}(u,v)\lek\)。对于树上的路径进行分类:经过根;不经过根。第二类路径点可以通过递归子树求出。对于经过根的路径,可以一遍dfs求出每个点到根的距离\(\text{dis}(u)\)。问题转化为求\(\text{dis}(u)......
  • 虚树【学习笔记】
    为什么要用虚树?例题在某些树上问题中,对于某次询问,我们并不需要用到全部的树上的点:例如,例题中:总点数\(n\le2.5\times10^5\)询问次数\(m\le5\times10^5\)询问的点数\(\sumk_i\le5\times10^5\)我们可以发现其实每次询问均摊下来的询问点数k并不多,但如果每次询问都......