--- tags: 基礎算法 title: 分治法2 (divide & conquer No.2) --- # 分治法2 (divide & conquer No.2) :::info - 預備知識:基礎DP ::: ## 再談逆序數對 - *如果沒聽過逆序數對,請看[這篇筆記](https://hackmd.io/Uw2u5wLDSQOo3D2kgdQLLg)* :::info 題目: - 給定序列$A_1, A_2, A_3, ..., A_n$,求出有幾個數組$(i,j,k)$滿足 - $1 <= i < j < k <= n$ 且 $A_i > A_j > A_k$ constraints: - $n <= 10^5$ ::: :::success 如果你已經會做兩個數字的逆序數對,這題應該不難。 對於原本的逆序數對,我們合併時使用兩個指針求出 這邊只講MERGE的部份~ 一樣令左半序列$L$, 右半序列$R$ - 先對於$L$的每個元素求出在自己左邊且比自己大的數有幾個(求二個數字的逆序數對,$O(|L|log|L|)$) - 再對於$R$的每個元素求出在自己右邊且比自己小的數有幾個(求二個數字的逆序數對,$O(|R|log|R|)$) 最後合併的方式其實就跟二維的一樣了~ - $L$序列一個元素+$R$序列兩個元素 - $L$序列兩個元素+$R$序列一個元素 完成~ Time Complexity: $O(n×log^2n)$ ::: ## 用分治法解一維DP問題?! *如果能用分治法解DP問題,之後講到的「區間查詢問題」就不再是問題了~* :::info 直接看例題ㄅ 題目: - 給定序列$A_1, A_2, A_3, ..., A_n$,求整個區間的最大連續子區間和 Constraints: - $n <= 2×10^6$ - $-10^9 <= A_i <= 10^9$ ::: :::success 用DP解的話大家都會ㄅ 這邊用分治解法~ 一樣講MERGE的地方就好。 一樣令左半序列$L$, 右半序列$R$。 我們發現,整個區間的答案可能是$L$的答案,也可能是$R$的答案,還有可能是橫跨$L,R$的區間。 那我們不如維護區間的最大前綴合&最大後綴合(?) - 令$prefix\_max(L)$為$L$的最大前綴和,$R$也如此 - 令$suffix\_max(L)$為$L$的最大後綴和,$R$也如此 我們發現這個區間的答案是 - $max\{L$的答案$,R$的答案$,suffix\_max(L)+prefix\_max(R)\}$ 然後,我們如何維護prefix_max跟suffix_max呢? - $prefix\_max(L,R) = max(prefix\_max(L),sum(L)+prefix\_max(R))$ - $suffix\_max(L,R) = max(suffix\_max(R),sum(R)+suffix\_max(L))$ 這麼一來,合併複雜度$O(1)$ Time Complexity: $O(n)$ ::: 再看一個經典題 :::info - 給定序列$A_1, A_2, A_3, ..., A_n$,需要選取一些數字,使的選取數字之和最大。 - 任意兩個被選取的數字不得相鄰。 Constraints: - $n <= 2×10^6$ - $0 <= A_i <= 10^9$ ::: :::success 解法也很簡單~ 一樣令左半序列$L$, 右半序列$R$。 為了處理數字不相鄰的問題,這次我們多維護一些東西: - 整個序列中選取合法數字的最大和 - 第一個數不選取的情況下,選取合法數字的最大和 - 最後一個元數不選取的情況下,選取合法數字的最大和 - 第一個數跟最後一個數都不選取的情況下,選取合法數字的最大和 維護這幾個資訊,我們也成功把合併複雜度壓到$O(1)$ 至於怎麼維護,就給各位自己去想喔~ Time Complexity: $O(n)$ ::: 最後給個Bonus :::info 各位自己想想看喔~ - 使用分治法求LIS - [之前的LIS筆記](https://hackmd.io/5np7TpYDRqiJHruJfuIDmA) - 三圍偏序問題 - [ZJ c571]((https://zerojudge.tw/ShowProblem?problemid=c571)) :::