BZOJ 4448: [Scoi2015]情报传递 DFS序+主席树

对与每一个时刻用主席树维护一下 DFS 序即可.          

LCA 的话树剖求解比较快. 

code:  

#include <cstdio>   
#include <string> 
#include <cstring>
#include <algorithm>  

#define N 200006 

using namespace std; 

namespace IO { 

    void setIO(string s) 
    {
        string in=s+".in"; 
        string out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        freopen(out.c_str(),"w",stdout); 
    }

}; 

namespace se {   

    #define lson t[x].ls 
    #define rson t[x].rs 

    struct node { 
        int ls,rs,sum;      
    }t[N*50]; 
    int tot; 

    int newnode() { return ++tot; }   

    void build(int &x,int l,int r) 
    {
        x=newnode(); 
        if(l==r) return; 
        int mid=(l+r)>>1;  
        build(lson,l,mid),build(rson,mid+1,r);         
    }

    int update(int pre,int l,int r,int p,int v) 
    {        
        int x=newnode();     
        t[x]=t[pre];   
        t[x].sum=t[pre].sum+v;    
        if(l==r) return x;   
        int mid=(l+r)>>1;   
        if(p<=mid)  lson=update(t[pre].ls,l,mid,p,v); 
        else rson=update(t[pre].rs,mid+1,r,p,v);    
        return x; 
    }    

    int query(int x,int l,int r,int L,int R) 
    {
        if(!x) return 0; 
        if(l>=L&&r<=R)  return t[x].sum; 
        int re=0,mid=(l+r)>>1;  
        if(L<=mid)  re+=query(lson,l,mid,L,R); 
        if(R>mid)   re+=query(rson,mid+1,r,L,R);   
        return re;  
    }

    #undef lson 
    #undef rson 

}; 

int n,edges,dfn; 
int hd[N],to[N],nex[N],st[N],ed[N],dep[N],size[N],son[N],top[N],fa[N],Rt[N];    

void add(int u,int v) 
{  
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
}   

void dfs1(int u) 
{
    st[u]=++dfn; 
    size[u]=1; 
    for(int i=hd[u];i;i=nex[i]) 
    {
        dep[to[i]]=dep[u]+1;   
        dfs1(to[i]); 
        size[u]+=size[to[i]]; 
        if(size[to[i]]>size[son[u]])  son[u]=to[i];    
    } 
    ed[u]=dfn; 
}

void dfs2(int u,int tp) 
{ 
    top[u]=tp;
    if(son[u])  dfs2(son[u],tp); 
    for(int i=hd[u];i;i=nex[i]) 
    {
        int v=to[i]; 
        if(v==son[u])  continue;   
        dfs2(v,v);   
    }
}

int LCA(int x,int y) 
{  
    while(top[x]!=top[y]) 
    {
        dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; 
    } 
    return dep[x]<dep[y]?x:y; 
}
 
int main() 
{ 
    // IO::setIO("input");  
    int i,j,q,rt=0,tim=0; 
    scanf("%d",&n); 
    for(i=1;i<=n;++i) 
    {
        int ff; 
        scanf("%d",&ff); 
        fa[i]=ff;     
        if(!ff)  rt=i;   
        else add(ff,i);  
    }   
    dfs1(rt);   
    dfs2(rt,rt);            
    se::build(Rt[0],1,n);   
    scanf("%d",&q);      
    for(i=1;i<=q;++i) 
    {   
        int op; 
        tim=i;  
        Rt[tim]=Rt[tim-1];   
        scanf("%d",&op);   
        if(op==1) 
        {     
            int x,y,c; 
            scanf("%d%d%d",&x,&y,&c);    
            printf("%d ",dep[x]+dep[y]-2*dep[LCA(x,y)]+1);  
            if(c>=tim)   printf("0\n"); 
            else 
            {                 
                int x1=0,x2=0,x3=0,x4=0,lca=LCA(x,y);
                x1=se::query(Rt[tim-c-1],1,n,1,st[x]);   
                x2=se::query(Rt[tim-c-1],1,n,1,st[y]);      
                x3=se::query(Rt[tim-c-1],1,n,1,st[lca]);    
                x4=se::query(Rt[tim-c-1],1,n,1,st[fa[lca]]);   
                printf("%d\n",x1+x2-x3-x4);   
            }
        } 
        else 
        {
            int t; 
            scanf("%d",&t);               
            Rt[tim]=se::update(Rt[tim],1,n,st[t],1);                
            if(ed[t]<n) Rt[tim]=se::update(Rt[tim],1,n,ed[t]+1,-1);   
        }
    }       
    return 0; 
}

  

posted @ 2019-12-26 09:35  EM-LGH  阅读(120)  评论(0编辑  收藏  举报