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\n",as[i]-1);
    
    return 0;
}

 

posted @ 2018-12-24 21:59  AKCqhzdy  阅读(199)  评论(0编辑  收藏  举报