虚树

我们用单调栈来建虚树,如果求 lca 的复杂度为 \(O(\log n)\) 的话,整个求虚树的复杂度应该为 \(O(n\log n)\)

整体思路为我们用首先把所有关键点按照 dfs 序排序,然后首先把 \(1\) 节点加入栈。整个过程我们维护一条左链。我们考虑往里面加入一个新的关键点。求一下这个点和栈顶的 lca。

如果这个这个点和整个单调栈中的点都在一个链上,我们就入栈。

否则,我们不停的弹栈,同时链上栈中元素之间的边,接着,如果这个 lca 不在栈中的话,加入这个 lca 并连相应的边,最后加入我们的新关键点。

注意:

  • 如果 \(1\) 节点也是关键点注意不要重复入栈,判掉。
  • 最后栈中元素连边。

代码:

inline void bu(){
    top=0;
    sort(v.begin(),v.end(),cmp);sta[++top]=1;head2[1]=0;tail2=0;
    for(int now:v){
        vis[now]=1;
        if(now==1) continue;
        int nl=ge(now,sta[top]);
        if(nl!=sta[top]){
            while(top>=2&&id[nl]<id[sta[top-1]]) Add2(sta[top-1],sta[top]),top--;
            if(id[nl]>id[sta[top-1]]) head2[nl]=0,Add2(nl,sta[top]),sta[top]=nl;
            else Add2(nl,sta[top--]);
        }
        sta[++top]=now;head2[now]=0;
    }
    for(int i=1;i<top;i++) Add2(sta[i],sta[i+1]);
}
posted @ 2023-07-13 21:31  NuclearReactor  阅读(17)  评论(0编辑  收藏  举报