一、凸包的定義
凸包(\(Convex\) \(Hull\))是一個計算幾何(圖形學)中的概念。
在一個實數向量空間\(V\)中,對於給定集合\(X\),所有包含\(X\)的凸集的交集\(S\)被稱為\(X\)的凸包。
X的凸包可以用\(X\)內所有點(\(X_1\),...\(X_n\))的凸組合來構造.
在二維歐幾里得空間中,凸包可想象為一條剛好包着所有點的橡皮圈。
用不嚴謹的話來講,給定二維平面上的點集,凸包就是將最外層的點連接起來構成的凸多邊形,它能包含 點集 中所有的點。

如上圖所示,點集中外層的點構成的凸多邊形就構成了能夠包含所有點的凸包,其中連接相鄰頂點構成的邊越來越平緩,或者說斜率越來越小構成的一組點叫做上凸殼,而相鄰的邊,斜率越來越大的一組點叫做下凸殼。

關於斜率,同學們可以認為是直線與橫軸在第一象限的夾角,夾角越小,斜率越小,夾角越大,斜率越大,換句話說:斜率越小,越貼近x軸,斜率越大,越貼近y軸。
如圖所示,開始只有頂點\(A、B\)構成的凸包,然后加入第三點\(C_1\),顯然\(BC_1\)的斜率是高於\(AB\)的,因此\(AB\),\(BC_1\)構成了一個下凸殼;
但是如果新加的點不是\(C_1\)而是\(C_2\),\(BC_2\)的斜率小於\(AB\),那么\(AB\)和\(BC2\)就不能構成下凸殼了,因為不能作為點集的下邊界,不能包含在\(AB\)下面卻在\(AC_2\)上面的點,(這樣就不是凸包,而是凹包了!)
因此,加入\(C_2\)后,\(AC_2\)將成為下凸殼新的邊界了。對於平面上的三點\(A(x_1,y_1),B(x_2,y_2),C(x_3,y_3)\),(其中\(x_1 < x_2 < x_3,y_1 < y_2 < y_3\)),\(AB\)的斜率小於\(BC_1\)的斜率才能使得\(AB\)、\(BC_1\)形成下凸殼。
二、凸包用途
以本節的三道題為例,寫一下我對凸包在此專題中作用的理解:
考慮什么時候一個點可以取到最小值
對於點\(J_2\),當以\(x\)為關鍵字排序后的兩個相鄰的點\(J_1\)和\(J_3\)(在此題中對應\(c[j]\)的單調性)
當斜率\(k_1<k_0<k_2\)時,此點就是最優轉移點
考慮什么時候一個點可能可以取到最小值,什么時候一定不能
如下圖,當斜率\(k_1<k_2\)時,\(J_2\)是有機會的,此時三個點下凸
當斜率\(k_1>=k_2\)時,\(J_2\)不會有一點機會,此時三個點上凸
此處模擬了一條斜率為\(k\)的直線,上面的點集是它的前序依賴值,問我們,當此直線方程取前序依賴值集中的哪一個點,使得直線方程的截距最小。
答案顯而易見,就是從下到上遇到的第一個斜率比自己高的那個點。
非常幸運的是,凸包的維護,也是要求每兩個點組成的直線,斜率不斷長大,才是下凸殼。換句話說,如果我們用一個單調隊列維護了一個下凸殼的話,那么,在這個集合中通過二分查找,很容易能夠找到比當前直線斜率高的第一個點,從而求出此直線方程的截距最小值。
整理一下:
1、我們從小到大,不斷的向二維空間中增加一些符合直線方程的點,並動態維護好一個凸包(單調隊列)。
2、當新的點想要加入時,它需要找出它的前序點中截距最小的點,可以利用二分搜索在凸包隊列中快速找出。
3、我們只要維護好凸包,永遠都在下凸殼的組成點集中查找,其它點都肯定不是答案,這樣明顯提速。再加上面2中提到的單調性+二分,速度杠杠滴~