Review-并查集(Bzoj3673)

来源:互联网 发布:photoshopcs6 mac 编辑:程序博客网 时间:2024/06/05 09:57

3673: 可持久化并查集 by zky

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 478  Solved: 196
[Submit][Status]

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


题解:

可持续数据结构的思想:利用时间戳,加上时间一维,就比如在我们的三维世界加上第四维-—时间轴,这样就可以回到原来的状态。具体实现是用线段树表示每个点的父亲节点,当父亲节点修改时,在造出需要的修改的节点,因此空间消耗有点大。

代码:

program pro;var    ke,ls,rs:array[0..2000005]of longint;    n,m,tot:longint;    fa,deep,root:array[0..2000005]of longint;procedure swap(var x,y:longint);var    k:longint;begin    k:=x; x:=y; y:=k;end;procedure make(var now:longint; l,r:longint);var    mid:longint;begin    if now=0 then    begin        inc(tot); now:=tot;    end;    if l=r then    begin        fa[now]:=l;        exit;    end;    mid:=(l+r)shr 1;    make(ls[now],l,mid);    make(rs[now],mid+1,r);end;procedure modify(l,r,x:longint; var y:longint; pos,val:longint);var    mid:longint;begin    inc(tot); y:=tot;    if l=r then    begin        fa[y]:=val; deep[y]:=deep[x];        exit;    end;    ls[y]:=ls[x]; rs[y]:=rs[x];    mid:=(l+r)shr 1;    if pos<=mid then modify(l,mid,ls[x],ls[y],pos,val)    else modify(mid+1,r,rs[x],rs[y],pos,val);end;function query(k,l,r,pos:longint):longint;var    mid:longint;begin    if l=r then exit(k);    mid:=(l+r)shr 1;    if pos<=mid then exit(query(ls[k],l,mid,pos))    else exit(query(rs[k],mid+1,r,pos));end;procedure add(k,l,r,pos:longint);var    mid:longint;begin    if l=r then    begin        inc(deep[k]); exit;    end;    mid:=(l+r)shr 1;    if pos<=mid then add(ls[k],l,mid,pos)    else add(rs[k],mid+1,r,pos);end;function find(k,x:longint):longint;var    xx:longint;begin    xx:=query(k,1,n,x);    if fa[xx]=x then exit(xx)    else exit(find(k,fa[xx]));end;procedure main;var    i,j,re,a,b,aa,bb,tmp:longint;begin    readln(n,m);    make(root[0],1,n);    for i:=1 to m do    begin        read(re);        case re of        1:        begin            root[i]:=root[i-1];            readln(a,b);            aa:=find(root[i],a); bb:=find(root[i],b);            if fa[aa]=fa[bb] then continue;            if deep[aa]>deep[bb] then swap(aa,bb);            modify(1,n,root[i-1],root[i],fa[aa],fa[bb]);            if (deep[aa]=deep[bb]) then add(root[i],1,n,fa[bb]);        end;        2:        begin            readln(tmp);            root[i]:=root[tmp];        end;        3:        begin            root[i]:=root[i-1];            readln(a,b);            aa:=find(root[i],a); bb:=find(root[i],b);            if fa[aa]=fa[bb] then writeln(1) else writeln(0);        end;        end;    end;end;beginassign(input,'3673.in'); reset(input);    main;close(input);end.



0 0
原创粉丝点击