3673: 可持久化并查集 by zky
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 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
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
Sample Output
10
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;
begin
assign(input,'3673.in'); reset(input);
main;
close(input);
end.

本文介绍了一种数据结构——可持久化并查集,它通过加入时间维度实现了状态回溯的功能。适用于需要记录历史状态及快速查询的场景。文章提供了具体的实现代码示例。
254

被折叠的 条评论
为什么被折叠?



