有乙個劃分為n列的星際戰場,各列依次編號為1,2,…,n。
有n艘戰艦,也依次編號為1,2,…,n,其中第i號戰艦處於第i列。
有t條指令,每條指令格式為以下兩種之一:
1、m i j,表示讓第i號戰艦所在列的全部戰艦保持原有順序,接在第j號戰艦所在列的尾部。
2、c i j,表示詢問第i號戰艦與第j號戰艦當前是否處於同一列中,如果在同一列中,它們之間間隔了多少艘戰艦。
現在需要你編寫乙個程式,處理一系列的指令。
輸入格式
第一行包含整數t,表示共有t條指令。
接下來t行,每行乙個指令,指令有兩種形式:m i j或c i j。
其中m和c為大寫字母表示指令型別,i和j為整數,表示指令涉及的戰艦編號。
輸出格式
你的程式應當依次對輸入的每一條指令進行分析和處理:
如果是m i j形式,則表示艦隊排列發生了變化,你的程式要注意到這一點,但是不要輸出任何資訊;
如果是c i j形式,你的程式要輸出一行,僅包含乙個整數,表示在同一列上,第i號戰艦與第j號戰艦之間布置的戰艦數目,如果第i號戰艦與第j號戰艦當前不在同一列上,則輸出-1。
資料範圍
n≤30000,t≤500000
輸入樣例:
4m 2 3
c 1 2
m 2 4
c 4 2
輸出樣例:-11
首先考慮如何判斷兩艘戰艦是否在處於同一列中:將某乙個集合中的所有元素移入另乙個集合中,很容易可以想到並查集,所以這一步我們可以採用並查集來解決。
接下來考慮如何計算同一列兩艘戰艦之間的戰艦數量:並查集維護的是某個節點與根節點之間的關係,我們可以維護乙個距離陣列d,d[i]表示的是節點 i 到根節點的距離,那麼兩艘戰艦(a、b)之間的的戰艦數量 cnt
cntcn
t 就為
c nt
=∣d[
a]−d
[b]∣
−1,a
≠b
cnt = |d[a] - d[b]| - 1, a ≠ b
cnt=∣d
[a]−
d[b]
∣−1,
a=bcn
t=0,
a=
bcnt = 0, a = b
cnt=0,
a=b那麼問題就轉化為如何維護 d 陣列呢?因為是到根節點的距離,所以我們可以在每次插入的時候只修改根節點到新的根節點之間的距離,然後在每次路徑壓縮的時候再來修改其它節點到新的根節點之間的距離(具體見**),而如何跟新集合a到集合b根節點的距離呢?需要引入size陣列,size[i]用於記錄集合中的節點數量,這裡 i 必須為集合根節點的編號,因為我們只會對根節點的值進行修改,也只會用到根節點的值。
#include
#include
#include
#include
using
namespace std;
const
int n =
30010
;int n, m;
int p[n]
, d[n]
, s[n]
;int
find
(int x)
return p[x];}
intmain()
else}}
return0;
}
銀河英雄傳說
公元五八 一年,地球居民遷至金牛座 第二行星,在那裡發表銀河聯邦創立宣言,同年改元為宇宙歷元年,並開始向銀河系深處拓展。宇宙歷七九九年,銀河系的兩大軍事集 在巴公尺利恩星域爆發戰爭。泰山壓頂集 宇宙艦隊司令萊因哈特率領十萬餘艘戰艦出征,氣吞山河集 點名將楊威利組織麾下三萬艘戰艦迎敵。楊威利擅長排兵布...
銀河英雄傳說
公元五八 一年,地球居民遷至金牛座 第二行星,在那裡發表銀河聯邦創立宣言,同年改元為宇宙歷元年,並開始向銀河系深處拓展。宇宙歷七九九年,銀河系的兩大軍事集 在巴公尺利恩星域爆發戰爭。泰山壓頂集 宇宙艦隊司令萊因哈特率領十萬餘艘戰艦出征,氣吞山河集 點名將楊威利組織麾下三萬艘戰艦迎敵。楊威利擅長排兵布...
vijos P1443 銀河英雄傳說
並查集 瞎搞 思路 對於合併和查詢是否存在於同一集合好說 關鍵就是查詢之間的戰艦數量的問題 可以利用樹上字首和的思想來實現 用sum i 表示i節點到根的距離 那麼考慮維護 在a隊接到b隊的過程中 需要維護a的節點到根的距離 很顯然a中所有節點的sum需要加上b中節點的個數 那就再開乙個tot i ...