• 【BZOJ3674】可持久化并查集加强版


    可持久化并查集我觉得就是可持久化数组的一种应用。可持久化数组,顾名思义,就是有历史版本的数组,那么如果我们暴力修改储存的话,修改O(n)查询O(1),空间O(n*m),这样肯定不可行,那么我们发现主席树有这样的功能,他可以快速复制,修改O(log),查询O(log),空间(m*log),是一个可行的方案。然后我们可持久化f数组维护fa,每次按照深度启发式合并,不进行路径压缩,这样能保证时间复杂度位单次O(log^2),空间复杂度为O(2*n+m*log)。我不知道为什么不路径压缩,路径压缩是完全可以的,但是他的时间复杂度和空间复杂度似乎都不如不路径压缩看,而且似乎并不好打。

    #include <cstdio>
    using namespace std;
    inline void read(int &sum){
      register char ch=getchar();
      for(sum=0;ch<'0'||ch>'9';ch=getchar());
      for(;ch>='0'&&ch<='9';sum=(sum<<1)+(sum<<3)+ch-'0',ch=getchar());
    }
    const int N=200010;
    struct Segment_Tree{
      Segment_Tree *ch[2];int f,deep;
      void* operator new(size_t);
    }*root[N],*null,*C,*mempool;
    int n,m;
    void* Segment_Tree :: operator new(size_t){
      if(C==mempool)C=new Segment_Tree[(1<<15)+10],mempool=C+(1<<15)+10;
      return C++;
    }
    inline void build(Segment_Tree *&p,int l,int r){
      p=new Segment_Tree,p->deep=p->f=0;
      if(l==r){
        p->f=l,p->deep=1,p->ch[0]=p->ch[1]=null;
        return;
      }
      build(p->ch[0],l,(l+r)>>1);
      build(p->ch[1],((l+r)>>1)+1,r);
    }
    inline void insert(Segment_Tree *&p,Segment_Tree *last,int pos,int key,int l,int r){
      p=new Segment_Tree,*p=*last;
      if(l==r){
        p->f=key;return;
      }
      if(pos<=((l+r)>>1))insert(p->ch[0],last->ch[0],pos,key,l,((l+r)>>1));
      else insert(p->ch[1],last->ch[1],pos,key,((l+r)>>1)+1,r);
    }
    inline void update(Segment_Tree *p,int pos){
      register int l=1,r=n;
      while(l!=r){
        if(pos<=((l+r)>>1)){
          p=p->ch[0],r=((l+r)>>1);
        }else{
          p=p->ch[1],l=((l+r)>>1)+1;
        }
      }
      p->deep++;
    }
    inline int deep(Segment_Tree *p,int pos){
      register int l=1,r=n;
      while(l!=r){
        if(pos<=((l+r)>>1)){
          p=p->ch[0],r=((l+r)>>1);
        }else{
          p=p->ch[1],l=((l+r)>>1)+1;
        }
      }
      return p->deep;
    }
    inline int F(Segment_Tree *p,int pos){
      register int l=1,r=n;
      while(l!=r){
        if(pos<=((l+r)>>1)){
          p=p->ch[0],r=((l+r)>>1);
        }else{
          p=p->ch[1],l=((l+r)>>1)+1;
        }
      }
      return p->f;
    }
    inline int find_root(Segment_Tree *p,int x){
      int fa=F(p,x);
      return fa==x?x:find_root(p,fa);
    }
    inline void Init(){
      null=new Segment_Tree,null->ch[0]=null->ch[1]=null,null->f=0,null->deep=0;
      read(n),read(m);
      build(root[0],1,n);
    }
    inline void Work(){
      register int ans=0,opt,a,b,x,y,d1,d2;
      for(register int i=1;i<=m;i++){
        read(opt);
        switch(opt){
          case 1:read(a),a^=ans,read(b),b^=ans;
                x=find_root(root[i-1],a),y=find_root(root[i-1],b);
                if(x==y){
                  root[i]=root[i-1];
                  break;
                }
                d1=deep(root[i-1],x),d2=deep(root[i-1],y);
                if(d1>d2)x^=y^=x^=y;insert(root[i],root[i-1],x,y,1,n);
                if(d1==d2)update(root[i],y);
                break;
          case 2:read(a),a^=ans;  
                root[i]=root[a];break;
          case 3:read(a),read(b),a^=ans,b^=ans;
                root[i]=root[i-1];
                x=find_root(root[i],a),y=find_root(root[i],b);
                if(x==y)puts("1"),ans=1;
                else puts("0"),ans=0;
                break;
        }
      }
    }
    int main(){
      Init();
      Work();
      return 0;
    }
  • 相关阅读:
    FindBugs详解
    Java杂项
    Ubuntu 16.04安装DB2 Express C v11.1
    h5搜索功能
    与安卓交互的上传图片 与 上传语音、视频
    获取后台轮播图图片,让其自动播放
    点赞和关注功能
    split、replace、indexof、substr 用法 (获取后台富文本框内容,截取图片)
    ttyu平台进页面获取阅读量
    图片放大预览功能
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7297329.html
Copyright © 2020-2023  润新知