【JZOJ1826】銀河英雄傳說

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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章