description
公元五八○一年,地球居民遷移至金牛座α第二行星,在那裏發表銀河聯邦創立宣言,同年改元爲宇宙曆元年,並開始向銀河系深處拓展。
宇宙歷七九九年,銀河系的兩大軍事集團在巴米利恩星域爆發戰爭。泰山壓頂集團派宇宙艦隊司令萊因哈特率領十萬餘艘戰艦出征,氣吞山河集團點名將楊威利組織麾下三萬艘戰艦迎敵。
楊威利擅長排兵佈陣,巧妙運用各種戰術屢次以少勝多,難免恣生驕氣。在這次決戰中,他將巴米利恩星域戰場劃分成30000列,每列依次編號爲1, 2, …, 30000。之後,他把自己的戰艦也依次編號爲1, 2, …, 30000,讓第i號戰艦處於第i列(i = 1, 2, …, 30000),形成“一字長蛇陣”,誘敵深入。這是初始陣形。當進犯之敵到達時,楊威利會多次發佈合併指令,將大部分戰艦集中在某幾列上,實施密集攻擊。合併指令爲M i j,含義爲讓第i號戰艦所在的整個戰艦隊列,作爲一個整體(頭在前尾在後)接至第j號戰艦所在的戰艦隊列的尾部。顯然戰艦隊列是由處於同一列的一個或多個戰艦組成的。合併指令的執行結果會使隊列增大。
然而,老謀深算的萊因哈特早已在戰略上取得了主動。在交戰中,他可以通過龐大的情報網絡隨時監聽楊威利的艦隊調動指令。
在楊威利發佈指令調動艦隊的同時,萊因哈特爲了及時瞭解當前楊威利的戰艦分佈情況,也會發出一些詢問指令:C i j。該指令意思是,【詢問電腦,楊威利的第i號戰艦與第j號戰艦當前是否在同一列中,如果在同一列中,那麼它們之間佈置有多少戰艦。】
作爲一個資深的高級程序設計員,你被要求編寫程序分析楊威利的指令,以及回答萊因哈特的詢問。
最終的決戰已經展開,銀河的歷史又翻過了一頁……
analysis
-
經典NOI題目,正解是並查集
-
和普通並查集不同的是,我們還要記錄兩個東西:
-
bi是每一個點的深度,ci是每一個點在當前集合裏的深度
-
每次更改father時,把深度也調整一下
-
然後就容易知道答案了
code
var
father,b,c:array[0..30000]of longint;
n,i,j,x,y:longint;
ch:char;
function getfather(x:longint):longint;
begin
if father[x]=x then exit(x);
getfather:=getfather(father[x]);//注意這個地方不可以直接寫成father[x]=getfather(x),而要放在後面
b[x]:=b[x]+b[father[x]]-1;// 原因很簡單,因爲這個點的深度是父節點的深度+1
father[x]:=getfather;//如果先路徑壓縮再計算深度,那麼當前點的深度會變成深度爲1的祖先+1=2,答案就會錯誤
end;
procedure union(x,y:longint);
var
i,j:longint;
begin
i:=getfather(x);
j:=getfather(y);
if i<>j then
begin
father[i]:=j;
b[i]:=b[i]+c[j];
c[j]:=c[i]+c[j];
end;
end;
function solve(x,y:longint):longint;
begin
if getfather(x)=getfather(y)then exit(abs(b[x]-b[y])-1);
exit(-1);
end;
begin
readln(n);
for i:=1 to 30000 do
begin
father[i]:=i;
b[i]:=1;
c[i]:=1;
end;
for i:=1 to n do
begin
readln(ch,x,y);
if ch='M' then union(x,y)
else writeln(solve(x,y));
end;
end.