zoukankan      html  css  js  c++  java
  • 虚树

    虚树

    虚树看起来很简单的样子。

    事实上也的确很简单。

    我们先来知道一下虚树是用来干什么的。

    对于一个问题,我们知道他可以做树型(dp)

    (dp)的类型大致是给你(k)个关键点,而(dp)的结果与这些关键点有关系

    (m)组询问,需要你对于每组询问进行回答。

    并且有条件(sum k)(n)是同阶的。

    如果每次对于所有点都做一遍(dp),复杂度达到了(O(nm))

    所以,我们需要把复杂度往(sum k)上靠。

    这样,就有了虚树。

    我们仔细想想,每次(dp)的时候是否真的所有点都需要计算呢?

    答案显然是不。我们只需要计算那些对于答案有影响的点。

    再来思考一下哪些点对于答案有影响呢?

    关键点显然是有影响的。

    同时,(dp)的时候显然需要合并答案,因此,关键点之间的(LCA)也是有影响的

    所以,我们构建的虚树包括两种点:关键点,(LCA),还需要一个毫无关系的节点作为根节点来合并最后的答案。

    因此,构建虚树就相当于把这些点拿出来,然后按照原树中的方式连接好就行了。

    怎么做呢?

    先考虑怎么求出(LCA),显然不可能(O(k^2))去求

    事实上,我们只需要把关键点按照(dfs)序((dfn))排序,然后把相邻点的(LCA)求出来就好了

    这样子,我们最多可能拿到(2k)个点(所以注意一下数组的大小,是(2)倍)

    现在考虑怎么构建。

    把现在所有的点按照(dfn)排序,维护一个栈,栈中的点全部在同一条链上,节点的深度从栈顶到栈底递减。

    对于新加入的一个节点,检查新的节点是否在栈顶节点的子树中,

    如果在,直接加入栈中,仍然满足链的性质,并且栈顶就是当前点在虚树上的父亲。

    证明?因为已经按照(dfn)排序,因此一条链肯定从上至下依次出现。

    如果当前点不在栈顶节点的子树中,证明当前栈顶节点的子树中已经没有虚树中的点了

    直接把它弹出来,继续检查即可。

    这样我们就构建出了虚树了。

    大致的代码如下:

    sort(&p[1],&p[K+1],cmp);
    for(int i=K;i>1;--i)p[++K]=LCA(p[i],p[i-1]);p[++K]=1;
    sort(&p[1],&p[K+1],cmp);K=unique(&p[1],&p[K+1])-p-1;
    for(int i=1,top=0;i<=K;++i)
    {
    	while(top&&low[S[top]]<dfn[p[i]])--top;
    	Add(S[top],p[i],0);S[++top]=p[i];
    }
    

    至于虚树要怎么用???

    那就因题而异了。

  • 相关阅读:
    eclipse导入源码
    servlet文件上传及下载
    MediatorPattern(中介者模式)-----Java/.Net
    IteratorPattern(迭代器模式)-----Java/.Net
    CommandPattern(命令模式)-----Java/.Net
    ResponsibilityChainPattern(责任链模式)-----Java/.Net
    TemplateMethodPattern(模板方法模式)-----Java/.Net
    InterpreterPattern(解释器模式)-----Java/.Net
    ProxyPattern(代理模式)-----Java/.Net
    FlyweightPattern(享元模式)-----Java/.Net
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9066403.html
Copyright © 2011-2022 走看看