zoukankan      html  css  js  c++  java
  • BZOJ2167 : 公交车站

    设$f[i]$表示$i$往上通过一趟公交车能到达的深度最小的祖先,这可以通过将公交车按$lca$深度从小到大排序后用并查集染色得到。

    对于每个询问:

    $1.x==y$

    $ans=0$。

    $2.x$是$y$的祖先

    交换$x,y$,变成$3$。

    $3.y$是$x$的祖先:

    在$f$上倍增即可。

    $4.x->lca->y$

    首先倍增求出一步就能到$lca$的那个点$t$,然后沿着$lca$往下贪心爬一步到达$z$,再加上$z$到$y$的距离。

    找$z$的时候,考虑二分查找,那么只需要判断两个点之间是否可以只用一条公交线路到达。

    这等价于判断是否有公交线路起点在$t$子树内,终点在$z$子树内,可持久化线段树维护。

    时间复杂度$O(nlog^2n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=10010,K=15,M=320010;
    int n,m,Q,i,j,x,y,z,g[N],v[N<<1],nxt[N<<1],ed,G[N],V[N<<1],NXT[N<<1],ED;
    int p[N],fa[N][K],f[N],d[N],size[N],son[N],st[N],en[N],dfn,q[N],top[N];
    int T[N],l[M],r[M],val[M],tot;
    struct E{int x,y,z;}e[N];
    inline bool cmp(const E&a,const E&b){return d[a.z]<d[b.z];}
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    inline void ADD(int x,int y){V[++ED]=y;NXT[ED]=G[x];G[x]=ED;}
    void dfs(int x){
      size[x]=1;d[x]=d[f[x]]+1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
        f[v[i]]=x;
        dfs(v[i]),size[x]+=size[v[i]];
        if(size[v[i]]>size[son[x]])son[x]=v[i];
      }
    }
    void dfs2(int x,int y){
      q[st[x]=++dfn]=x;top[x]=y;
      if(son[x])dfs2(son[x],y);
      for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
      en[x]=dfn;
    }
    inline int lca(int x,int y){
      for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
      return d[x]<d[y]?x:y;
    }
    inline int up(int x,int k){
      while(1){
        int t=st[x]-st[top[x]];
        if(k<=t)return q[st[x]-k];
        k-=t+1;
        x=f[top[x]];
      }
    }
    inline int go(int x,int y){
      if(x==y)return 0;
      if(d[fa[x][K-1]]>d[y])return -1;
      int t=1;
      for(int i=K-1;~i;i--)if(d[fa[x][i]]>d[y])x=fa[x][i],t+=1<<i;
      return t;
    }
    int ins(int x,int a,int b,int c){
      int y=++tot;
      val[y]=val[x]+1;
      if(a==b)return y;
      int mid=(a+b)>>1;
      if(c<=mid)l[y]=ins(l[x],a,mid,c),r[y]=r[x];else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c);
      return y;
    }
    int ask(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return val[x];
      int mid=(a+b)>>1,t=0;
      if(c<=mid)t=ask(l[x],a,mid,c,d);
      if(d>mid)t+=ask(r[x],mid+1,b,c,d);
      return t;
    }
    inline bool check(int x,int y){return ask(T[en[x]],1,n,st[y],en[y])>ask(T[st[x]-1],1,n,st[y],en[y]);}
    inline int query(int x,int y){
      if(st[x]<=st[y]&&en[y]<=en[x])return go(y,x);
      if(st[y]<=st[x]&&en[x]<=en[y])return go(x,y);
      int z=lca(x,y),t=0;
      if(d[fa[x][K-1]]>d[z])return -1;
      for(int i=K-1;~i;i--)if(d[fa[x][i]]>d[z])x=fa[x][i],t+=1<<i;
      int l=0,r=d[y]-d[z]-1,mid,o=d[y]-d[z];
      while(l<=r)if(check(x,up(y,mid=(l+r)>>1)))r=(o=mid)-1;else l=mid+1;
      o=go(y,up(y,o));
      if(o<0)return -1;
      return t+o+1;
    }
    void dfs3(int x){
      for(int i=1;i<K;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
      for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x])dfs3(v[i]);
    }
    int F(int x){return p[x]==x?x:p[x]=F(p[x]);}
    inline void col(int x,int y){for(x=F(x);d[x]>=d[y];x=F(x))fa[x][0]=y,p[x]=f[x];}
    int main(){
      read(n),read(m),read(Q);
      for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
      dfs(1);
      dfs2(1,1);
      for(i=1;i<=m;i++){
        read(e[i].x),read(e[i].y),e[i].z=lca(e[i].x,e[i].y);
        x=e[i].x,y=e[i].y,z=e[i].z;
        if(x==y)continue;
        ADD(st[x],st[y]);
        ADD(st[y],st[x]);
      }
      sort(e+1,e+m+1,cmp);
      for(i=1;i<=n;i++)p[i]=fa[i][0]=i;
      for(i=1;i<=m;i++)col(e[i].x,e[i].z),col(e[i].y,e[i].z);
      dfs3(1);
      for(i=1;i<=n;i++)for(T[i]=T[i-1],j=G[i];j;j=NXT[j])T[i]=ins(T[i],1,n,V[j]);
      while(Q--){
        read(x),read(y);
        z=query(x,y);
        if(z>0)z--;
        printf("%d
    ",z);
      }
      return 0;
    }
    

      

  • 相关阅读:
    hdu 5723 Abandoned country 最小生成树 期望
    OpenJ_POJ C16G Challenge Your Template 迪杰斯特拉
    OpenJ_POJ C16D Extracurricular Sports 打表找规律
    OpenJ_POJ C16B Robot Game 打表找规律
    CCCC 成都信息工程大学游记
    UVALive 6893 The Big Painting hash
    UVALive 6889 City Park 并查集
    UVALive 6888 Ricochet Robots bfs
    UVALive 6886 Golf Bot FFT
    UVALive 6885 Flowery Trails 最短路
  • 原文地址:https://www.cnblogs.com/clrs97/p/6426449.html
Copyright © 2011-2022 走看看