• [学习笔记] 虚树


    今天考了个模拟赛,虚树的题我拿(LCT)粗暴卡过,然后被各路神仙疯狂嘲讽,然后就奋发图强,来学了个虚树。

    虚树的概念

    先放一个例题吧:[SDOI 2011]消耗战

    例题单个询问的树形DP可以说是非常简单了,但是多个询问就会(GG),于是我们痛定思痛,发现其实我们并不需要整棵树来转移,我们只需要得到每一个目标节点和他们的(LCA)所构成的树即可,而树的边权即为树上两点在原树上的路径中的最小值。

    那么像这种由目标节点和他们的(LCA)所构成的树即为虚树。

    虚树的构造

    既然知道了啥是虚树,那么就让我们再来看看虚树应该怎么构造吧。

    其实虚树的构造过程类似(dfs)

    我们先整个类似(dfs)的栈,这个栈里存的只有虚树上需要的节点。

    那么对于一个新加入的目标节点 (x)(显然目标节点要按(dfs)序排序再加入),我们分两种情况讨论:

    • (x) 在以(stk[top])为根的子树中

    • (x) 不在以(stk[top])为根的子树中

    第一种情况很简单,直接把 (x) 加入栈即可。

    让我们来具体研究一下第二种情况:

    我们找到次栈顶结点((stak[top-1]))(x)(LCA) ,我们只需要一直把次栈顶与(LCA)比较,若 (dep[stk[top-1]]>dep[LCA]) ,那么便将给栈顶((stk[top]))和次栈顶((stk[top-1]))之间连一条边。

    如果某一时刻(dep[stk[top-1]]<dep[LCA]&&dep[stk[top]]==dep[LCA]),那么就说明(LCA)就是(stk[top]),我们只需要连上((stk[top],x))这条边即可。

    那么如果(dep[stk[top]]>dep[LCA])呢?

    这就说明(LCA)并不在虚树中,我们需要连上((stk[top],LCA)),然后将(LCA)(x) 加入栈中。

    最后,给出建虚树代码:

    void ins(int x){
    	int l=lca(x,stk[top],0);
    	while (top>1&&dep[l]<dep[stk[top-1]]){
    		E[stk[top]].push_back(stk[top-1]);
    		E[stk[top-1]].push_back(stk[top]);
    		--top;
    	}
    	if (dep[stk[top]]>dep[l]){
    	    E[stk[top]].push_back(l);
    	    E[l].push_back(stk[top]);
    	    --top;
    	}
    	if (stk[top]!=l) stk[++top]=l;
    	stk[++top]=x;
    }
    
  • 相关阅读:
    mysq 日期相减
    说说时间观与时间管理——北漂18年(71)
    ionic之切换开关
    ionic之单选框
    SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE locks在RR模式下可以看到最新的记录
    14.5.2.3 Consistent Nonlocking Reads 一致性非锁定读
    14.5.2.2 autocommit, Commit, and Rollback
    14.5.2 事务隔离级别
    对于唯一索引使用唯一条件搜索, InnoDB 只锁定找到的index record,不是它之前的区间
    mysql explain 解释
  • 原文地址:https://www.cnblogs.com/WR-Eternity/p/11740574.html
Copyright © 2020-2023  润新知