ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

虚树 virtual-tree

2021-10-01 15:00:57  阅读:215  来源: 互联网

标签:元素 加入 处理 Lca tree virtual 栈中 虚树


我们发现,如果一棵树中真正需要处理的点很少,而总共点数很多时,可以只处理那些需要的点,而忽略其他点。

因此我们可以根据那些需要的点构建虚树,只保留关键点。

oi-wiki上对虚树的介绍

我们根据一下方式建立虚树:

  • 现将所有需要处理的关键按照欧拉序排序。

  • 用一个栈维护一条从根节点到上一个处理过个点的链(虚树上的链)。

  • 考虑将一个新的点加入虚树:

    • 求出这个点与栈顶元素的 \(Lca\) 。

    • 如果 \(Lca\) 不是栈顶元素:

      • 在栈中只保留栈中的链与现在加入点所在的链的公共部分加上一个上一次处理完的链中元素(通过 \(Lca\) 的 \(dfn\) )。

      • 如果 \(Lca\) 已经在栈中,则弹出那个多余的元素。

      • 如果 \(Lca\) 还不在栈中,则将 \(Lca\) 与多余元素连边,并加入 \(Lca\) 。

    • 把新的点加入栈中。

    • 处理完后把栈中的链也连边连上。

注意:由于整个图需要用到的边与点很少,所以在每次新建虚树的时候不能全局清空,而是在把一个新的点加入栈中的时候清空这个点连过的边。

建立虚树代码:

inline void build()
{
	 sort(query+1,query+m+1,cmp),tot=tp=0;
	 sta[++tp]=1,hea[1]=0;
	 for(int i=1,l;i<=m;i++)
	 {
	 	 if(query[i]==1) continue;
	 	 l=Lca(query[i],sta[tp]);
	 	 if(l!=sta[tp])
	 	 {
	 	 	 while(dfn[l]<dfn[sta[tp-1]])
			 {
			 	 Lca(sta[tp-1],sta[tp]); // 这里用来处理这一条虚树中的边的权值。
				 add(sta[tp-1],sta[tp],minn);
				 tp--;
			 }
	 	 	 if(sta[tp-1]!=l)
			 {
			 	 hea[l]=0;
				 Lca(l,sta[tp]); // 这里用来处理这一条虚树中的边的权值。
				 add(l,sta[tp],minn);
				 sta[tp]=l;
			 }
	 	 	 else
			 {
			 	 Lca(l,sta[tp]); // 这里用来处理这一条虚树中的边的权值。
				 add(l,sta[tp--],minn);
			 }
		 }
		 hea[query[i]]=0,sta[++tp]=query[i];
	 }
	 for(int i=1;i<tp;i++)
	 {
	 	 Lca(sta[i],sta[i+1]); // 这里用来处理这一条虚树中的边的权值。
		 add(sta[i],sta[i+1],minn);
	 }
}

建立完之后就可以在虚树上处理答案了,这样即使多次询问,复杂度也是和选中关键点个数同阶的。

例题:

标签:元素,加入,处理,Lca,tree,virtual,栈中,虚树
来源: https://www.cnblogs.com/EricQian/p/15359399.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有