您的位置:首页 > 其它

【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树

2016-06-07 23:05 471 查看
没什么好说的。

可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲。

Q:不是很清楚空间开多大,每次询问父亲操作后修改的节点个数是不确定的。。

#include<bits/stdc++.h>
#define ll long long
#define N 20005
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
return x*f;
}
int n,m,rt
,tot;
int f[N*100],ls[N*100],rs[N*100];
void build(int &x,int l,int r){
x=++tot;
if(l==r){f[x]=l;return;}
int mid=l+r>>1;
build(ls[x],l,mid);
build(rs[x],mid+1,r);
}
int find(int x,int l,int r,int pos){
if(l==r)return f[x];
int mid=l+r>>1;
if(pos<=mid)return find(ls[x],l,mid,pos);
else return find(rs[x],mid+1,r,pos);
}
void update(int pre,int &x,int l,int r,int pos,int val){
x=++tot;ls[x]=ls[pre];rs[x]=rs[pre];
if(l==r){f[x]=val;return;}
int mid=l+r>>1;
if(pos<=mid)update(ls[pre],ls[x],l,mid,pos,val);
else update(rs[pre],rs[x],mid+1,r,pos,val);
}
int findfa(int ti,int x){
int tmp=find(rt[ti],1,n,x);
if(tmp==x)return x;
else{
tmp=findfa(ti,tmp);
update(rt[ti],rt[ti],1,n,x,tmp);
return tmp;
}
}
void unite(int ti,int x,int y){
int fx=findfa(ti,x),fy=findfa(ti,y);
if(fx<fy)swap(x,y),swap(fx,fy);
if(fx!=fy)update(rt[ti],rt[ti],1,n,fx,fy);
}
int main(){
n=read();m=read();
build(rt[0],1,n);
for(int i=1;i<=m;i++){
rt[i]=rt[i-1];
int t=read();
if(t==1){
int x=read(),y=read();
unite(i,x,y);
}
else if(t==2){
int k=read();rt[i]=rt[k];
}
else{
int x=read(),y=read();
findfa(i,x)==findfa(i,y)?puts("1"):puts("0");
}
}
return 0;
}


View Code

3673: 可持久化并查集 by zky

Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 1506 Solved: 677
[Submit][Status][Discuss]

Description

n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0

0<n,m<=2*10^4

Input

Output

Sample Input

5 6

1 1 2

3 1 2

2 0

3 1 2

2 1

3 1 2

Sample Output

1

0

1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: