zoukankan      html  css  js  c++  java
  • BZOJ3514 : Codechef MARCH14 GERALD07加强版

    以边编号为权值

    用Link-cut Tree维护最大生成树

    对于新加的第i条边(u,v)

    a[i]表示当a[i]这条边加入后连通块个数会减少

    若u==v则a[i]=m

    若u与v不连通则连上,a[i]=0

    若u与v连通则a[i]为u,v路径上最小值,将那条边断开,连上这条边

    查询[l,r]等价于查询[l,r]里有多少a[i]<l

    主席树维护

    时间复杂度$O((m+k)log m)$

    #include<cstdio>
    #define N 400010
    #define E 200010
    #define M 4000010
    int f[N],son[N][2],val[N],min[N],tmp[N];bool rev[N];
    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 swap(int&a,int&b){int c=a;a=b;b=c;}
    inline int Min(int a,int b){return a<b?a:b;}
    inline bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
    inline void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;}
    inline void pb(int x){if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;}
    inline void up(int x){min[x]=Min(val[x],Min(min[son[x][0]],min[son[x][1]]));}
    inline void rotate(int x){
      int y=f[x],w=son[y][1]==x;
      son[y][w]=son[x][w^1];
      if(son[x][w^1])f[son[x][w^1]]=y;
      if(f[y]){
        int z=f[y];
        if(son[z][0]==y)son[z][0]=x;
        if(son[z][1]==y)son[z][1]=x;
      }
      f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
    }
    inline void splay(int x){
      int s=1,i=x,y;tmp[1]=i;
      while(!isroot(i))tmp[++s]=i=f[i];
      while(s)pb(tmp[s--]);
      while(!isroot(x)){
        y=f[x];
        if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
        rotate(x);
      }
      up(x);
    }
    inline void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
    inline int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
    inline void makeroot(int x){access(x);splay(x);rev1(x);}
    inline void link(int x,int y){makeroot(x);f[x]=y;access(x);}
    inline void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);}
    inline void cut(int x,int y){makeroot(x);cutf(y);}
    inline int ask(int x,int y){makeroot(x);access(y);splay(y);return min[y];}
    int n,m,i,k,type,x,y,u[E],v[E],a[E],tot,l[M],r[M],sum[M],head[E],last;
    int ins(int x,int a,int b,int c){
      int y=++tot;
      sum[y]=sum[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 query(int x,int a,int b,int c){
      if(!x)return 0;
      if(b<=c)return sum[x];
      int mid=(a+b)>>1,t=query(l[x],a,mid,c);
      if(c>mid)t+=query(r[x],mid+1,b,c);
      return t;
    }
    int main(){
      read(n);read(m);read(k);read(type);
      for(i=0;i<=n;i++)val[i]=min[i]=1000000000;
      for(i=1;i<=m;i++)val[i+n]=min[i+n]=i;
      for(i=1;i<=m;i++){
        read(u[i]);read(v[i]);
        if(u[i]==v[i])a[i]=m;
        else if(root(u[i])==root(v[i]))a[i]=ask(u[i],v[i]),cut(u[a[i]],a[i]+n),cut(v[a[i]],a[i]+n),link(u[i],i+n),link(v[i],i+n);
        else link(u[i],i+n),link(v[i],i+n);
      }
      for(i=1;i<=m;i++)head[i]=ins(head[i-1],0,m,a[i]);
      while(k--){
        read(x),read(y);
        if(type)x^=last,y^=last;
        printf("%d
    ",last=n-query(head[y],0,m,x-1)+query(head[x-1],0,m,x-1));
      }
      return 0;
    }
    

      

  • 相关阅读:
    接口测试01
    mysql主从
    linux下配置JDK
    linux常用命令
    mysql基本语句
    线程与进程
    loadrunner函数
    设计模式-模板方法模式
    设计原则-CRP合成复用原则
    设计原则-LOD迪米特法则
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403247.html
Copyright © 2011-2022 走看看