首页 > 代码库 > 【BZOJ3674】可持久化并查集加强版
【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;}
【BZOJ3674】可持久化并查集加强版
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。