zoukankan      html  css  js  c++  java
  • bzoj4538: [Hnoi2016]网络

    被肉老师d得血肉模糊

    上午自己yy了一发dfs序+树状数组+cdq,结果发现自己子树里面的情况是处理不了的...(orz claris KDT踩过

    正解就是整体二分,然后每次像扫描线一样扫过,就能解决时间问题啦

    主要的问题是判断是否有一条路径不经过当前点

    转化成判断是否所有路径都经过当前点,我们进行如下操作:

    对于每一条路径,dfs序以后,两个端点+1,公共祖先-1,公共祖先的父亲-1

    然后我们可以发现,假如一条路径不经过当前点,对当前点的贡献就是0,否则就是1

    这样就可以logn判出来了

    LCA可以O(1) (然而对复杂度计算没什么区别,都是O(nlog^2n))

    rose:常数巨大

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct node
    {
        int x,y,next;
    }a[210000];int len,last[110000];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    int fa[110000],dep[110000];
    int z,L[110000],R[110000];//用于计算子树权值和 
    int u,ys[110000],f[30][210000];//用于求LCA 
    void dfs(int x)
    {
        L[x]=++z;f[0][++u]=x;ys[x]=u;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fa[x])
            {
                fa[y]=x;
                dep[y]=dep[x]+1;
                dfs(y);
                f[0][++u]=x;
            }
        }
        R[x]=z;
    }
    //~~~~~~~~~~~~~~~~~~~ys~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    int Bin[30],Log[210000];
    void get_st()
    {
        Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2;
        Log[1]=0;for(int i=2;i<=u ;i++)Log[i]=Log[i/2]+1;
        dep[0]=(1<<30);
        for(int j=1;j<=25;j++)
            for(int i=1;i+Bin[j]-1<=u;i++)
                if(dep[f[j-1][i]]<dep[f[j-1][i+Bin[j-1]]])f[j][i]=f[j-1][i];
                else f[j][i]=f[j-1][i+Bin[j-1]];
    }
    int LCA(int x,int y)
    {
        if(ys[x]>ys[y])swap(x,y);
        x=ys[x];y=ys[y];
        int k=Log[y-x+1];
        if(dep[f[k][x]]<dep[f[k][y-Bin[k]+1]])return f[k][x];
        else return f[k][y-Bin[k]+1];
    }
    //~~~~~~~~~~~~~~~~~~~LCA~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    //------------------------------------------init------------------------------------------------------------
    
    int n,s[110000];
    int lowbit(int x){return x&-x;}
    void change(int x,int k){ while(x<=n+10){s[x]+=k;x+=lowbit(x);} }
    int getsum(int x){ int ret=0; while(x>0){ret+=s[x];x-=lowbit(x);} return ret; }
    //~~~~~~~~~~~~~~~~~~~~bit~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    struct qnode{int op,x,y,d,t;}q[410000],lq[410000],rq[410000];int cnt,as[210000];
    void erfen(int l,int r,int st,int ed)
    {
        if(l>r)return ;
        if(st>ed)return ;
        
        int mid=(l+r)/2,e=0,llen=0,rlen=0;
        for(int i=st;i<=ed;i++)
        {
            if(q[i].op==0)
            {
                if(q[i].d>=mid)
                {
                    e++;
                    int lca=LCA(q[i].x,q[i].y);
                    change(L[q[i].x],1),change(L[q[i].y],1);
                    change(L[lca],-1);
                    if(fa[lca]!=0)change(L[fa[lca]],-1);
                    rq[++rlen]=q[i];
                }
                else lq[++llen]=q[i];
            }
            else if(q[i].op==1)
            {
                if(q[i].d>=mid)
                {
                    e--;
                    int lca=LCA(q[i].x,q[i].y);
                    change(L[q[i].x],-1),change(L[q[i].y],-1);
                    change(L[lca],1);
                    if(fa[lca]!=0)change(L[fa[lca]],1);
                    rq[++rlen]=q[i];
                }
                else lq[++llen]=q[i];
            }
            else
            {
                int d=getsum(R[q[i].x])-getsum(L[q[i].x]-1);
                if(d==e)lq[++llen]=q[i];
                else rq[++rlen]=q[i],as[q[i].y]=mid;
            }
        }
        
        for(int i=1;i<=llen;i++)q[st+i-1]=lq[i];
        for(int i=1;i<=rlen;i++)q[st+llen+i-1]=rq[i];
        erfen(l,mid-1,st,st+llen-1);
        erfen(mid+1,r,st+llen,ed);
    }
    
    //----------------------------------------------------------------------------------------
    
    bool b[210000];
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int Q,x,y;
        scanf("%d%d",&n,&Q);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            ins(x,y),ins(y,x);
        }
        dep[1]=1;fa[1]=0;dfs(1);
        get_st();
        
        cnt=0;int mmax=0;
        memset(b,false,sizeof(b));
        for(int i=1;i<=Q;i++)
        {
            scanf("%d",&q[i].op);q[i].t=i;
            if(q[i].op==0)
            {
                scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].d),q[i].d++;
                mmax=max(mmax,q[i].d);
                if(q[i].x>q[i].y)swap(q[i].x,q[i].y);
            }
            else if(q[i].op==1)
            {
                scanf("%d",&x);b[x]=true;
                q[i].x=q[x].x,q[i].y=q[x].y,q[i].d=q[x].d;
            }
            else scanf("%d",&q[i].x),q[i].y=++cnt;
        }
        int qq=Q+1;
        for(int i=1;i<=Q;i++)
            if(q[i].op==0&&b[i]==false)
            {
                q[++Q]=q[i];
                q[Q].op=1,q[Q].t=qq;
            }
        
        erfen(1,mmax,1,Q);
        for(int i=1;i<=cnt;i++)
            printf("%d
    ",as[i]-1);
        
        return 0;
    }
  • 相关阅读:
    [Linux起步]常用命令
    Eclipse被SD杂志评为最佳开源工具
    [一点一滴学英语]20050921
    [一点一滴学英语]20050920
    [一点一滴学英语]20050919
    Longhorn (Vista) 推迟发布的背后
    最快速度找到内存泄漏
    重载(overload)、覆盖(override)、隐藏(hide) 详解
    HTTP请求和响应格式
    Skia之四——SkGradientShader篇
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10171235.html
Copyright © 2011-2022 走看看