---
# System prepended metadata

title: 分治法2 (divide & conquer No.2)
tags: [基礎算法]

---

---
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))
:::