比较巧妙的并查集,考察对并查集的引申应用。维护三个数组:
a[i]表示i到pre[i]中间有方块的个数
pre[i]表示i所在集合编号,即根
c[i]表示以i为标志的集合中元素个数,只有当pre[i]=i的时候c[i]才有意义
合并时,只需进行如下操作:
1、对读入的x、y分别进行路径压缩,直到找到真根为止
2、合并x、y两个集合,主要步骤如下:
pre[x]:=y;a[x]:=c[y];c[y]:=c[y]+c[x];
这道题目倒是和银河英雄传说有些相似之处,可以对比着来做一下。
Program Cubes;//By_Poetshy
Const
maxn=30000;
Var
i,n,p,q :Longint;
pre,a,c :Array[1..maxn]of Longint;
ch :Char;
Procedure Combine(x,y:Longint);
begin
pre[x]:=y;
a[x]:=c[y];
inc(c[y],c[x]);
end;
Function Find_Set(i:Longint):Longint;
var fa:Longint;
begin
if pre[i]=i then exit(i);
fa:=pre[i];
pre[i]:=Find_Set(pre[i]);
inc(a[i],a[fa]);
exit(pre[i]);
end;
Procedure Union(p,q:Longint);
begin
Combine(Find_Set(p),Find_Set(q));
end;
BEGIN
readln(n);
for i:=1 to maxn do
begin
pre[i]:=i;c[i]:=1;a[i]:=0;
end;
for i:=1 to n do
begin
read(ch);
if ch='M' then
begin
readln(p,q);
Union(p,q);
end else
begin
readln(p);
pre[p]:=Find_Set(p);
writeln(a[p]);
end;
end;
END.