虚树 virtual-tree

虚树是一种在处理大量节点但真正关心的点很少的情况下,优化算法效率的数据结构。通过对关键点按欧拉序排序并构建虚树,只处理需要的节点,降低复杂度。在虚树中,新节点加入时,找到它与栈顶元素的最近公共祖先(LCA),根据LCA更新栈状态,并连接相应边。这种方法适用于多轮询问的情况,确保复杂度与关键点数量同阶。
摘要由CSDN通过智能技术生成

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

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

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值