首页 > 代码库 > 可持久化并查集的两种实现
可持久化并查集的两种实现
对于像UVA 11987 Almost Union-Find这样的题目,要求把一个元素从一个集合中剥离的情况,我们只需要新建一个节点然后……….
还是看代码吧:
inline void move(int x,int y) // 把x从y集合中剥离{ int fx = find(id[x]),fy = find(id[y]); if(fx == fy) return ; cnt[fx] --,sum[fx] -= x; id[x] = ++ tot; // 可持久化 f[id[x]] = fy; cnt[fy] ++,sum[fy] += x;}
这种方法主要是利用id[],在最初时id[i] = i,随着移动i,id[i]也在变化,在访问i时,我们需直接用id[i]代替。
对于 BZOJ 3674: 可持久化并查集加强版 我们就不能cheat 了,我们需要真的可持久化了。
因为并查集的所有信息都保存在fa[]里,所以,我们只需要用可持久化线段树实现一个可持久化数组就可以了。
ACCode:
#include<cstdio>#include<iostream>using namespace std;inline int read(){ int x=0;char ch=getchar(); while(ch>‘9‘||ch<‘0‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x;}int n,m,sz,last;int root[200005],ls[10000005],rs[10000005],v[10000005],deep[10000005];void build(int &k,int l,int r){ if(!k)k=++sz; if(l==r){v[k]=l;return;} int mid=(l+r)>>1; build(ls[k],l,mid); build(rs[k],mid+1,r);}void modify(int l,int r,int x,int &y,int pos,int val){ y=++sz; if(l==r){v[y]=val;return;} ls[y]=ls[x];rs[y]=rs[x]; int mid=(l+r)>>1; if(pos<=mid) modify(l,mid,ls[x],ls[y],pos,val); else modify(mid+1,r,rs[x],rs[y],pos,val);}int query(int k,int l,int r,int pos){ if(l==r)return k; int mid=(l+r)>>1; if(pos<=mid)return query(ls[k],l,mid,pos); else return query(rs[k],mid+1,r,pos);}void add(int k,int l,int r,int pos){ if(l==r){deep[k]++;return;} int mid=(l+r)>>1; if(pos<=mid)add(ls[k],l,mid,pos); else add(rs[k],mid+1,r,pos);}int find(int k,int x){ int p=query(k,1,n,x); if(x==v[p])return p; return find(k,v[p]);}int main(){ n=read();m=read(); build(root[0],1,n); int f,k,a,b; for(int i=1;i<=m;i++) { f=read(); if(f==1) { root[i]=root[i-1]; a=read();b=read();a=a^last;b=b^last; int p=find(root[i],a),q=find(root[i],b); if(v[p]==v[q])continue; if(deep[p]>deep[q])swap(p,q); modify(1,n,root[i-1],root[i],v[p],v[q]); if(deep[p]==deep[q])add(root[i],1,n,v[q]); } if(f==2) {k=read();k=k^last;root[i]=root[k];} if(f==3) { root[i]=root[i-1]; a=read();b=read();a=a^last;b=b^last; int p=find(root[i],a),q=find(root[i],b); if(v[p]==v[q])last=1; else last=0; printf("%d\n",last); } } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。