• 沒有找到結果。

根號算法

N/A
N/A
Protected

Academic year: 2022

Share "根號算法"

Copied!
121
0
0

加載中.... (立即查看全文)

全文

(1)

根號算法

(2)

暖身:優希的麻將牌

• 優希有 N 張麻將牌,每張麻將牌都有它的美好度 A_i

• 請你從這 N 張麻將牌挑一些,使得美好度的總和恰好為 K

• N <= 40

• K、每個 A_i、A_i 的總和都在 [1, 10^18]

(3)

優希的麻將牌

(4)

優希的麻將牌

• 我會做 2^N

• 2^40 大約是 10^12

• 好像有點大

• 輸光光(?

• 突然回講起上個禮拜DP教的內容(???

• 折半枚舉

(5)

優希的麻將牌

• 如果我們可以把問題分割成「規模相近」的兩部分

(6)

優希的麻將牌

3 7 12 5 1 4

• 左半邊可以組合出什麼組合呢

• {}、{3}、{7}、{12}、{3,7}、{3,12}、{7,12}、{3,7,12}

• 總和分別為 {0,3,7,12,10,15,19,33}

• 那麼, 右半邊呢

• {}、{5}、{1}、{4}、{5,1}、{1,4}、{5,4}、{5,1,4}

• 總和分別為 {0,5,1,4,6,5,9,10}

(7)

優希的麻將牌

• 如果我們想要湊出總和為 K

• 左半邊總和分別為 {0,3,7,12,10,15,19,33}

(8)

優希的麻將牌

• 分別考慮左邊的所有物品能湊出的價值

• 分別考慮右邊的所有物品能湊出的價值

• 需要多少時間? 分別需要 O(2^(N/2))

• 我們總共想要價值M

• 枚舉左邊集合的所有價值 i

• 如果在右邊找的到 M-i,那就成功了

• 如果右邊找不到M-i呢? 那就表示不存在「從左邊集合取出總和 i, 右邊集合取出總和 M-i 的方法」

(9)

優希的麻將牌

• 如何從右邊的集合中尋找 M-i 呢?

• 先排序! 再搜尋

(10)

優希的麻將牌

• 要如何找出一組可行的方案?

• Struct Mahjong {

• long long sum; //儲存總和

• bool used[N]; //紀錄每個元素是否用到

• }

(11)

優希的麻將牌

• Struct Mahjong { //照sum排序

• long long sum; //儲存總和

• int used; //紀錄每個元素是否用到,用一個int就夠了

• } //上面其實也可以用std::pair寫

(12)

優希的麻將牌

• 實做範例

(13)

暖身完畢

(14)

RMQ(Range minimum query)

• 給你一個長度 N 的序列 A[0], A[2], ..., A[N - 1]

• 緊接著 Q 筆詢問,每筆詢問是一個數對 x, y

• 請你回答 min{ A[x], A[x + 1], ..., A[y] }

• N <= 10^5, 0 <= A[i] <= 10^9

• A = {5, 2, 8, 1, 7}

• Query = {(0, 2), (1, 4), (2, 2)}

• 答案:2 1 8

(15)

RMQ(Range minimum

query)

(16)

RMQ(Range minimum query)

• 一部分?

• 每連續 k 個分一組,先把每組的最小值算好並存下來

• 對於詢問

• 綠色每塊都先算好了,時間花費是塊數:最多 N/k

• 紅色部份每個數字跑一遍,時間花費是一塊大小:最多 2k

• 下面的說明中,綠色會是「塊中元素」,紅色會是「邊邊元素」

(17)

RMQ(Range minimum query)

• 每次詢問 O(N/k + k) 取個好的 k?

• 算幾不等式:N/k + k <= 2*sqrt(N/k * k) = 2*sqrt(N)

• 在 N/k = k 也就是 k = sqrt(N) 時最小

(18)

RMQ(Range minimum query)

• 於是大家獲得了人生第一個根號算法 (?)

• RMQ 是很經典的問題

• 線段樹:預處理 O(N) - 詢問 O(log N)

sparse table:預處理 O(N log N) - 詢問 O(1)

• 線性 RMQ:預處理 O(N) - 詢問 O(1)

• 資芽只會教到線段樹

(19)

實作上

(20)

實做技巧

• 使用 0-base

• i/K 代表 i 在哪一塊

• 如果題目輸入 是1-base的話,

記得改成0-base (???

(21)

序列操作題

• 給你 A[1], A[2], ..., a[N]

• 兩種操作,總操作數量為Q

修改:把A[X] 設成 Y

查詢:輸出A[L]到A[R]中,有多少數字比Z小

(22)

序列操作題

• 優希(X) 老天(O) 告訴你,在試試看一次分塊~

(23)

序列操作題

(24)

序列操作題

• 試著把序列每 K 個分成一塊,每塊都維護成 sorted 的序列

預處理 O(N log N)

• 對於查詢操作:

邊邊的元素:O(K) 暴力比較

塊裡面的元素: O(log N) 二分搜有多少數字比 Z 小

總複雜度:O(K + N/K log N)

(25)

序列操作題

• 試著把序列每 K 個分成一塊,每塊都維護成 sorted 的序列

預處理 O(N log N)

• 對於查詢操作:

(26)

序列操作題

• 試著把序列每 K 個分成一塊,每塊都維護成 sorted 的序列

預處理 O(N log N)

• 對於查詢操作:

邊邊的元素:O(K) 暴力比較

塊裡面的元素: O(log N) 二分搜有多少數字比 Z 小

總複雜度:O(K + N/K log N)

• 對於修改操作:

O(K) 把該塊的 sorted 序列維護好

• 總複雜度:O(NK + N^2/K log N),取 K = sqrt(N) ?!?

(27)

序列操作題

• 試著把序列每 K 個分成一塊,每塊都維護成 sorted 的序列

預處理 O(N log N)

• 對於查詢操作:

邊邊的元素:O(K) 暴力比較

塊裡面的元素: O(log N) 二分搜有多少數字比 Z 小

總複雜度:O(K + N/K log N)

(28)

序列操作題:簡單實做

• 可以使用 std::vector 的 erase, insert,會比自己寫 swap還快一點點(不過複雜度還是O(N))

• 善用 std::lower_bound

(29)

中國人插隊問題

• 一開始給一個長度 N 的序列(index 1 到 N)

• 接著 Q 次操作,每次可能是

a. 請在第 i 個位子插入數字 x(index >= i 的數字往後一格)

b. 拔掉第 i 個位子的數字(index > i 的數字往前一格)

c. 請你回答第 i 個位子的數字是多少

• 例如

(30)

中國人插隊問題

• 天上傳來一道聲音,叫你再試試看剛剛那樣「分塊」

• 雖然這題用平衡樹炸下去是可以 O(N log N) ,不過這裡我們 先試試看分塊XD

(31)

中國人插隊問題

• 嘗試讓每塊儲存了 K 個數字 (若 K = 4)

A1 A2 A3 A4

1

(32)

中國人插隊問題

• 一開始給一個長度 N 的序列(index 1 到 N)

• 接著 Q 次操作,每次可能是

a. 請在第 i 個位子插入數字 x(index >= i 的數字往後一格)

b. 拔掉第 i 個位子的數字(index > i 的數字往前一格)

c. 請你回答第 i 個位子的數字是多少

• 例如

• 初始:1, 2, 3, 4, 5

• 操作:(a, 1, 6), (a, 7, 7), (c, 4), (b, 3), (b, 3), (c, 5)

• 過程:

• 6, 1, 2, 3, 4, 5

• 6, 1, 2, 3, 4, 5, 7 (輸出 3)

• 6, 1, 3, 4, 5, 7

• 6, 1, 4, 5, 7 (輸出 7)

(33)

中國人插隊問題

• 增加一個數字(第 3 個位置插入 B)

A1 A2 A3 A4

1

(34)

中國人插隊問題

• 增加一個數字(第 3 個位置插入 B)

A1 A2 A3 A4

A5 A6 A7 A8

A9 Aa Ab Ac

1

2

3

(35)

中國人插隊問題

• 增加一個數字(第 3 個位置插入 B)

A1 A2 A3 A4

1 B

(36)

中國人插隊問題

• 增加一個數字(第 3 個位置插入 B)

A1 A2 A3 A4

A5 A6 A7 A8

A9 Aa Ab Ac

1

2

3

B

(37)

中國人插隊問題

• 增加一個數字(第 3 個位置插入 B)

A1 A2 A3

1 B

(38)

中國人插隊問題

• 增加一個數字(第 3 個位置插入 B)

A1 A2 A3

A4 A5 A6 A7 A8

A9 Aa Ab Ac

1

2

3

B

(39)

中國人插隊問題

• 增加一個數字(第 3 個位置插入 B)

A1 A2 A3

1 B

(40)

中國人插隊問題

• 增加一個數字(第 3 個位置插入 B)

A1 A2 A3

A4 A5 A6 A7

1

2

3

B

A8 A9 Aa Ab

4 Ac

(41)

中國人插隊問題

• 一開始給一個長度 N 的序列(index 1 到 N)

• 接著 Q 次操作,每次可能是

a. 請在第 i 個位子插入數字 x(index >= i 的數字往後一格)

b. 拔掉第 i 個位子的數字(index > i 的數字往前一格)

c. 請你回答第 i 個位子的數字是多少

• 例如

(42)

中國人插隊問題

• 拔掉一個數字(拔掉第 3 個位置)

A1 A2 A3 A4

A5 A6 A7 A8

A9 Aa Ab Ac

1

2

3

(43)

中國人插隊問題

• 拔掉一個數字(拔掉第 3 個位置)

A1 A2 A4

1

(44)

中國人插隊問題

• 拔掉一個數字(拔掉第 3 個位置)

A1 A2 A4

A5 A6 A7 A8

A9 Aa Ab Ac

1

2

3

(45)

中國人插隊問題

• 拔掉一個數字(拔掉第 3 個位置)

A1 A2 A4 A5

1

(46)

中國人插隊問題

• 拔掉一個數字(拔掉第 3 個位置)

A1 A2 A4 A5

A6 A7 A8

A9 Aa Ab Ac

1

2

3

(47)

中國人插隊問題

• 拔掉一個數字(拔掉第 3 個位置)

A1 A2 A4 A5

1

(48)

中國人插隊問題

• 拔掉一個數字(拔掉第 3 個位置)

A1 A2 A4 A5

A6 A7 A8 A9

Aa Ab Ac

1

2

3

(49)

中國人插隊問題

• 一開始給一個長度 N 的序列(index 1 到 N)

• 接著 Q 次操作,每次可能是

a. 請在第 i 個位子插入數字 x(index >= i 的數字往後一格)

b. 拔掉第 i 個位子的數字(index > i 的數字往前一格)

c. 請你回答第 i 個位子的數字是多少

• 例如

(50)

中國人插隊問題

• 第 i 個數字:第 _______________ 塊的第 ___________ 個

A1 A2 A3 A4

A5 A6 A7 A8

A9 Aa Ab Ac

1

2

3

(51)

中國人插隊問題

• 第 i 個數字:第 (i - 1) / K + 1 塊的第 (i - 1) % K 個

A1 A2 A3 A4

1

(52)

中國人插隊問題

• 如果有一個可以 O(1) 從頭尾兩端刪除或增加的資料結構來維 護每一塊的話

(內部的查找、刪除都是與儲存的大小成線性)

• 插入:該塊內部 O(K)、之後每塊都要修一下 O(N / K)

• 刪除:該塊內部 O(K)、之後每塊都要修一下 O(N / K)

• 詢問:該塊內部 O(K)

• 找到第 i 塊?

• 把一堆這種資料結構開成陣列:O(1)

• 把一堆這種資料結構串起來(linked list):O(N / K)

• 總之全部合起來就是 O(K + N / K) => 又是根號了!

(53)

中國人插隊問題

如果

有一個可以 O(1) 從頭尾兩端刪除或增加的資料結構來 維護每一塊的話

(內部的查找、刪除都是與儲存的大小成線性)

(54)

第 Z 大

• 你有一個容器,一開始是空的

• 題目有三種操作,操作總數量是 Q:

加值:把 y 個數字 x 丟到容器裡面

減值:把 y 個數字 x 從容器中丟掉

查詢:詢問這個容器的第 Z 大的元素

• 1 <= Q, x <= 10^5, y <= 10^9 ,Z保證合法

(55)

第 Z 大

(56)

第 Z 大

• 當然,這題可以用平衡樹、線段樹輕鬆過

• 不過老天爺還是希望你可以使用分「塊」

• 不過是什麼「塊」呢?

(57)

第 Z 大

(58)

第 Z 大

• 對題目的「值域」分塊

• 對這題來講,就是對數字 x 去分塊

• 假設把值域 K 個做一塊,並且維護好每一塊的總和

也就是維護每一塊中,每一個數字出現過得次數和

(59)

第 Z 大

• 對題目的「值域」分塊

(60)

第 Z 大

• 對題目的「值域」分塊

• 對這題來講,就是對數字 x 去分塊

• 假設把值域 K 個做一塊,並且維護好每一塊的總和

也就是維護每一塊中,每一個數字出現過得次數和

• 加值、減值操作:

O(1) 更新那個數字出現的次數和,以及相對應塊的總和

• 查詢操作:

先花 O(C/K) 的時間,找到相對應的數字在哪一塊

C代表值域,本題來講C = 2*10^5

(61)

第 Z 大

• 對題目的「值域」分塊

• 對這題來講,就是對數字 x 去分塊

• 假設把值域 K 個做一塊,並且維護好每一塊的總和

也就是維護每一塊中,每一個數字出現過得次數和

• 加值、減值操作:

(62)

第 Z 大

• 對題目的「值域」分塊

• 對這題來講,就是對數字 x 去分塊

• 假設把值域 K 個做一塊,並且維護好每一塊的總和

也就是維護每一塊中,每一個數字出現過得次數和

• 加值、減值操作:

O(1) 更新那個數字出現的次數和,以及相對應塊的總和

• 查詢操作:

先花 O(C/K) 的時間,找到相對應的數字在哪一塊

C代表值域,本題來講C = 10^5

再花 O(K) 的時間,確認那個數字是哪一個數字

• 總複雜度為O(Q(C/K + K)),取 K = sqrt(C)

(63)

小咲的玩具

• NPSC 2019 國中組初賽 pB

• 你有 K 個 vector<int> v[K], vector 裡面總共會有 N 的元素

(64)

小咲的玩具

• 不是序列題,要怎麼分塊QAQ

(65)

小咲的玩具

(66)

小咲的玩具

• 先不管這個,現在假設詢問的 vector<int> 的 size 分別是 x, y,並且 x < y。

• 有沒有什麼方法可以得到答案(?)

• 方法一: O(xy) 暴力枚舉

(67)

小咲的玩具

• 先不管這個,現在假設詢問的 vector<int> 的 size 分別是

(68)

小咲的玩具

• 先不管這個,現在假設詢問的 vector<int> 的 size 分別是 x, y,並且 x < y。

• 有沒有什麼方法可以得到答案(?)

• 方法一: O(xy) 暴力枚舉

• 方法二: O(x + y) ,使用 雙指針(two pointer)

方法二不知道的話沒關係^^

• 方法三: O(x log y)

先維護好前綴和(prefix sum),之後對於 x 的每個元素,在 y 二分搜出哪個位置比他小

(69)

小咲的玩具

• 方法三: O(x log y)

(70)

小咲的玩具

• 把那先 vector<int> 分成兩類

胖 vector : size > K

瘦 vector : size <= K

(71)

小咲的玩具

(72)

小咲的玩具

• 把那先 vector<int> 分成兩類

胖 vector : size > K

瘦 vector : size <= K

• 先預處理詢問是兩個胖 vector 的所有答案

複雜度為: O( (N/K)^2 K log N ) = O(N^2/K log N)

(73)

小咲的玩具

• 把那先 vector<int> 分成兩類

(74)

小咲的玩具

• 把那先 vector<int> 分成兩類

胖 vector : size > K

瘦 vector : size <= K

• 先預處理詢問是兩個胖 vector 的所有答案

複雜度為: O( (N/K)^2 K log N ) = O(N^2/K log N)

• 對於其他的詢問(胖&瘦 或者 瘦&瘦),就直接算答案

複雜度為: O( N K log N)

(75)

小咲的玩具

• 把那先 vector<int> 分成兩類

胖 vector : size > K

瘦 vector : size <= K

(76)

小咲的玩具

• 把那先 vector<int> 分成兩類

胖 vector : size > K

瘦 vector : size <= K

• 先預處理詢問是兩個胖 vector 的所有答案

複雜度為: O( (N/K)^2 K log N ) = O(N^2/K log N)

• 對於其他的詢問(胖&瘦 或者 瘦&瘦),就直接算答案

複雜度為: O( N K log N)

• 總複雜度為: O(N^2/K log N + NK log N)

• 取 K = sqrt(N) ,可得複雜度為 O(N^1.5 log N)

(77)

在線與離線

對於剛剛很多題這種有多個詢問、操作的題目

• 在線 (online):程式/演算法 必須對前一個詢問或操作做出 回答,之後才能知道下一個詢問或操作。

(換句話說就是寫程式讀了一行就要馬上處理它)

(不用懷疑,一定有辦法作到這件事情XD)

(78)

在線與離線

• 為什麼要區分在線與離線呢?

• 哪一個比較簡單?

(79)

在線與離線

(80)

在線與離線

• 將來有很多離線比較簡單的例子在等著大家 A_A

(81)

在線與離線

• 其實不用等到將來,剛剛就有一個小小的例子(?)

(82)

Counting Triangles

• 給你一個 N 個點、M 條邊的簡單無向圖,請算出這張圖裡有幾 個「三角形」?

• 假設點被編號為 0 到 N - 1,三角形定義為一組數對 (x, y, z) 使得 0 <= x < y < z < N 且

(x, y)、(y, z)、(z, x) 均有邊

• 3 <= N <= 10^5

• 0 <= M <= 10^5

(83)

Counting Triangles

• 假設我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

• 那麼指定任一個點 v,我們能夠

a. 在 O(M) 時間內算出圖中有幾個包含 v 的三角形

(84)

Counting Triangles

• 假設我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

• 按照點度是否大於 K 分兩條

• 大於 K 的: 作法 a. (O(M))

• 不超過 K 的:作法 b. (O(d^2))

(85)

Counting Triangles

• 假設我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

(86)

Counting Triangles

• 假設我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

• 按照點度是否大於 K 分兩條

• 大於 K 的: 作法 a. (O(M))

• 這種點不超過 2M / K 個,總共 O(M^2 / K)

• 不超過 K 的:作法 b. (O(d^2))

• 這種點最多 N 個,每個 d 最大到 K,總共 O(N * K^2)

(87)

Counting Triangles

• 假設我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

• 按照點度是否大於 K 分兩條

(88)

Counting Triangles

假設

我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

• 那麼指定任一個點 v,我們能夠

a. 在 O(M) 時間內算出圖中有幾個包含 v 的三角形

b. 在 O(d^2) 時間內算出圖中有幾個包含 v 的三角形

(其中 d 為 v 的點度)

(89)

Counting Triangles

假設

我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

• 那麼指定任一個點 v,我們能夠

(90)

Counting Triangles

假設

我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

• 那麼指定任一個點 v,我們能夠

a. 在 O(M) 時間內算出圖中有幾個包含 v 的三角形

• 開一條 bool 陣列 adj,adj[i] 表示 v 與 i 之間是否有邊

b. 在 O(d^2) 時間內算出圖中有幾個包含 v 的三角形

(其中 d 為 v 的點度)

• 我們只在乎這邊給出的所有 (x, y) 詢問總共有幾個為 true 而且照 a. 的作法,只要一堆連續的詢問有共同端點我們就會做了

(91)

Counting Triangles

假設

我們能夠 O(1) 回答某個給定的 pair (x, y) 是否為圖上的一條邊

• 那麼指定任一個點 v,我們能夠

a. 在 O(M) 時間內算出圖中有幾個包含 v 的三角形

• 開一條 bool 陣列 adj,adj[i] 表示 v 與 i 之間是否有邊

(92)

Counting Triangles

• 開一條 bool 陣列 adj,adj[i] 表示 v 與 i 之間是否有邊 這條陣列怎麼寫?

(93)

Counting Triangles

(94)

Counting Triangles

• 開一條 bool 陣列 adj,adj[i] 表示 v 與 i 之間是否有邊 這條陣列怎麼寫?

(95)

Counting Triangles

• 另一個結論可能比較簡潔但思路似乎沒那麼自然的作法

(不過它或許會給大家一些啟示)

• 對於一條邊 (u, v),我們可以用 O(max(d_u, d_v)) 算出包含這條

(96)

Counting Triangles

• 把點度 >= sqrt(M) 的點叫做「重點」,其他叫「輕點」

• 重點只有 2*sqrt(M) 個

• 所以把「重點」對所有點的相鄰矩陣建出來

• 空間也只要 O(N sqrt(M))

• 對所有邊計算它被幾個三角形包含

• 輕點-輕點:用 O(max(d_u, d_v)) 的作法,也才 O(sqrt(M))

• 輕點-重點:用 O(min(d_u, d_v)) 的作法,也才 O(sqrt(M))

• 重點-重點:用 O(min(d_u, d_v)) 的作法,也才 ...?

(97)

Counting Triangles

• 對一個重點 u,如果計算某條邊 (u, v) 的 cost O(min(d_u, d_v)) 是 d_u

表示這條邊連接的點 v 具有 d_v > d_u

這種點 v 最多只有 2M / d_u 個

(98)

Counting Triangles

• 把點度 >= sqrt(M) 的點叫做「重點」,其他叫「輕點」

• 重點只有 2*sqrt(M) 個

• 所以把「重點」對所有點的相鄰矩陣建出來

• 空間也只要 O(N sqrt(M))

• 對所有邊計算它被幾個三角形包含

• 輕點-輕點:用 O(max(d_u, d_v)) 的作法,也才 O(sqrt(M))

• 輕點-重點:用 O(max(d_u, d_v)) 的作法,也才 O(sqrt(M))

• 重點-重點:用 O(min(d_u, d_v)) 的作法,也才 ...?

(99)

Counting Triangles

(100)

Counting Triangles

• 把點度 >= sqrt(M) 的點叫做「重點」,其他叫「輕點」

• 重點只有 2*sqrt(M) 個

• 所以把「重點」對所有點的相鄰矩陣建出來

• 空間也只要 O(N sqrt(M))

• 對所有邊計算它被幾個三角形包含

• 輕點-輕點:用 O(max(d_u, d_v)) 的作法,也才 O(sqrt(M))

• 輕點-重點:用 O(min(d_u, d_v)) 的作法,也才 O(sqrt(M))

• 重點-重點:用 O(max(d_u, d_v)) 的作法,也才 ...?

(101)

Counting Triangles

(102)

Counting Triangles

• 重點整理與啟發

第一種作法枚舉點、第二種作法枚舉邊

找出枚舉後的複雜度關鍵是什麼,對那個東西分大小

• 第一種作法用到的技巧

離線

可重複利用並快速歸零的 bool array

• 第二種作法用到的技巧

「重點」很少,可以維護一個「重點」X「所有點」的二維陣列

• 小心估複雜度

(103)

Mo’s algorithm

https://zerojudge.tw/ShowProblem?problemid=b417

• 先來看一道經典問題:「區間 種樹(X) 眾數(O)」

(104)

Mo’s algorithm

• 發明者:中國隊隊長莫濤

• 莫濤在解決「小Z的襪子」這題是,想到的演算法

https://www.lydsy.com/JudgeOnline/problem.php?id=

2038

• 於是乎,這個算法就被稱為「莫隊算法」,簡稱「莫隊」、

「Mo's algo」

(105)

Mo’s algorithm

• 莫隊算法(Mo's algorithm)是一個離線的算法

• 先把詢問「按照某種順序」排序過後,開始暴力硬算

• 題目的詢問從 [L, R] 轉移到 [L, R+1 or R-1] 時,必須

(106)

Mo’s algorithm

• 假設上面那張投影片的所有轉移時間都是 O(1)

• 那在「經過某種順序排序」後的詢問之下,時間複雜度就是

O(L指針移動的次數) + O(R指針移動的次數) + O(Q * 得到 答案的複雜度)

(107)

Mo’s algorithm

• 假設上面那張投影片的所有轉移時間都是 O(1)

(108)

Mo’s algorithm

• 先把序列每 K 個分成一塊。

(109)

Mo’s algorithm

(110)

Mo’s algorithm

• 先把序列每 K 個分成一塊。

• 排序詢問的方法為:

先按照 L 所在的塊排序

如果 L 所在的塊相同,則按照 R 排序

• 認真分析一下複雜度:

對於 L 指針:

對於 R 指針:

(111)

Mo’s algorithm

• 先把序列每 K 個分成一塊。

• 排序詢問的方法為:

先按照 L 所在的塊排序

如果 L 所在的塊相同,則按照 R 排序

(112)

Mo’s algorithm

• 先把序列每 K 個分成一塊。

• 排序詢問的方法為:

先按照 L 所在的塊排序

如果 L 所在的塊相同,則按照 R 排序

• 認真分析一下複雜度:

對於 L 指針:

O(N * K + N)

對於 R 指針:

O(N/K * N)

• 取 K = sqrt(N) ,大勝利~

• 於是乎,大家就得到一個 O(N sqrt (N))的區間眾數的解法

(113)

Mo’s algorithm

(114)

Mo’s algorithm

• 參考實做方式:指針的移動方式

(115)

Mo’s algorithm

(116)

Mo’s algorithm

• 進階版:帶修改莫隊

• 複雜度是 O(N^(5/3))

• 就留給大家上網查資料囉

(117)

Mo’s algorithm

(118)

題目

https://codeforces.com/contest/785/problem/E

• 給你一個長度為 N 的序列,一開始是 A[1] = 1, A[2] = 2, ..., a[N] = N

• Q 筆操作,每筆操作會給 X, Y ,請執行 swap(A[X],A[Y])

• 每筆操作完後,請輸出當前有多少對「逆序數對」

• N <= 2 * 10^5, Q <= 5 * 10^4

• TL = 4sec, ML = 512MB

• 當然這題有很多其他的方法、資料結構可以揍掉這題

(119)

題目

https://oj.icpc.tw/c/28/D

• 給你一個 N 個點、M 條邊的簡單無向圖

(120)

題目

區間第 K 大

• 給你一個長度為 N 的序列,並且有 Q 筆詢問

• 每筆詢問的內容是:[L, R]之中,第 K 大的數字是多少

• N, Q, 值域 <= 10^5

• 可能要把上面教的兩個算法合併在一起 (???

(121)

題目

SRM 675 Div.1 Middle

• 給你 n, x0, a, b,表示有一個長度 n 的數列:

x[0] = x0

for (int i = 1; i < n; i++)

x[i] = (x[i - 1] * a + b) % (10^9 + 7)

• 你要回答 Q 個詢問,每個詢問給你一個 k (0 <= k < n),

參考文獻

Outline

相關文件

• Michael Grossberg, Shree Nayar, Determining the Camera Response from Images: What Is Knowable, PAMI 2003. • Michael Grossberg, Shree Nayar, Modeling the Space of Camera

&lt; Notes for Schools: schools are advised to fill in the estimated minimum quantity and maximum quantity (i.e. the range of the quantity) of the items under Estimated Quantity

[r]

請舉出一個可以準確計算出根號值的數字。這類數字有什麼樣

[r]

[r]

[r]

Lecture by baluteshih Credit by zolution... Minimum