# f999 : SCP - A 特訓班 參考解法 [<<回主頁](https://hackmd.io/@r1cky/Sk2hKzga6) ### 1.$O(N^3)$ 暴力 這題如題目所說可以用$O(N^2)$枚舉每個$(L,R)$,每次檢查$O(N)$,所以是$O(N^3)$,但這複雜度顯然不好。 ### 2.暴力的優化:$O(N^2)$ 如果我們對於每個$R$枚舉,一開始$L=R$,接著每次$L$減少$1$,可以看成我一直把左邊一個個元素加入,利用DSU加一個元素是$O(1)$,而判斷的依據是當union之後,應該目前集合大小要是$R-L+1$,這樣代表全部是連通的,我們可透過是否連通來判斷條件,但加$N$次是$O(N)$,而$N$個$R$需要枚舉,時間複雜度是$O(N^2)$,還是不符合題目想要的。 ### 3.問題簡化 這題我們可以把$A$序列重新編碼變成$(1,2,...,N)$,問題變成以下: (問題#)給你一個$1\sim N$的某種排列$P$,問你有幾個$(P_L,...,P_R)$在經過排序之後,會變成一個連續公差$1$的等差數列?不過注意是環。 但這個問題由於有環很麻煩,我們考慮以下問題: (問題◇)給你一個$1\sim N$排列,請問有幾個$(P_L,...,P_R)$在經過排序後可以變成一個連續公差為1之序列? 註:其實這問題就是:https://neoj.sprout.tw/problem/788/ 我們可以證明,如果問題◇可以解決,我們也可以解決問題#,也就是我們最終要的問題。 ### 4.解決問題◇ 這個問題◇可以進一步的簡化成: 對於所有$(L,R)$區間,詢問符合$max(P_{L\sim R})-min(P_{L\sim r})=R-L$的數量。 這個問題可以透過分治的方式解決。 首先定義$F(L,R)$代表處理$L\sim R$區間,令$mid= \frac{L+R}{2}$,處理所有通過$mid$中點的區間,而其他的case則呼叫$F(L,mid)$與$F(mid+1,R)$,至於剩下要怎麼解決呢? 首先討論$(mid+1,R)$區間,當$R$增加的時候最大小值會單調,在上面放兩個指標(two pointers)。 而我們左邊從$mid$開始往左,有四個情況: 最大小值都在右邊: $-L=max-min-R$ 小在左大在右: $min-L=max-R$ 大在左小在右: $-max-L=-min-R$ 最大小值都在左邊: $min-max-L=-R$ 透過這些式子(其實只是移項),可以快速得到,方法是$L$移動時利用update算式的右邊(透過指標判斷目前狀態),查詢左邊,修改查詢都是$O(1)$,遞迴一層共$N$個,總共$logN$層,因此複雜度$O(NlogN)$。 ### 5.回歸正題 這題我們排序完後把數字$N$滾動到最右邊,接著分兩種情況,$R=N$以及$R\neq N$,我們討論以下: (1) $R\neq N$: $1\sim N-1$這個區間是一條線的、不是環,所以可以透過問題◇以$O(NlogN)$解決。 (2) $R=N$: 還記得前面的DSU方法嗎,針對這個case可以用DSU喔!因為只需要一個$R$,為$O(N)$ 結合(1)、(2),此問題可以以時間複雜度$O(NlogN)$、空間複雜度$O(N)$解決。