最長上公升子串行O nlogn

2021-08-30 11:25:36 字數 2315 閱讀 1723

令a[i]表示輸入第i個元素,d[i]表示從a[1]到a[i]中以a[i]結尾的最長子序列長度。對於任意的0 <  j <= i-1,如果a(j) < a(i),則a(i)可以接在a(j)後面形成乙個以a(i)結尾的新的最長上公升子串行。對於所有的 0 <  j <= i-1,我們需要找出其中的最大值。

dp狀態轉移方程:d[i] = max(j = 1, 2, 3, ..., i-1 且 a[j] < a[i])

對於最長不下降子串行,怎樣實現o(nlogn)演算法呢?我們知道o(n^2)的演算法複雜度高的原因就在於要更新d[i]的值,就必須在1~i-1中列舉找到最大的d[j]的值才能最終確定d[i]的值,於是我們可以這樣思考,能否直接把1~i-1中最大的d[i]的值儲存起來,從而實現直接檢索呢?於是就有了如下類似貪心的演算法(個人理解)。

/*預處理*/

const int maxn = 40010;

const int inf = 0x3f3f3f3f;

int n;

int a[maxn], s[maxn];

int d[maxn];

void init()

其中d[i]和是一樣的意義,而s陣列表示的意義是:所有最長上公升子串行長度為d[i]時的a[i]的最小值,請仔細理解這一段話,即s[d[i]] = min

舉例說明:

可以看出,s序列是嚴格的遞增序列,可以這樣理解:d[i'] = 2的最小值一定比d[i'']值為1的最小值大,因為d[i''] > d[i'],就這麼簡單。那麼知道了s的值有什麼用呢?或許聰明的讀者已經看出來了,對於最長不下降子串行,只要每次將乙個a[i]的值在s陣列中進行檢索,返回的小於等於a[i]最後乙個元素的下標的位置(或者「下乙個下標的位置」)一定就是d[i]的長度。

為什麼呢?因為在這下標前面的元素一定是小於a[i]的,所以d[i]的值也就是返回的下標的值,不懂的可以用筆模擬一下,這也是前面我們為什麼要這樣定義的目的所在。

這裡還有乙個地方要注意,就是最長上公升子串行的問題和最長不下降子串行的問題,如問題:1、2、3、5、5的結果是4還是5?待會我會給出滿意的解法。

另外正確的二分求上界的寫法,我也會給出,寫到這裡,筆者不得不感嘆:乙個正確的二分查詢也是很難寫的。。

/*最長不下降子串行 poj 1631*/

int bsearch(int x, int y, int v) //二分求上界

return x;} 

void dp()

printf("%d\n", ans);

}

如何求嚴格的最長上公升子串行呢?其實我們只要在二分時,把a[m] <= v改為a[m] < v即可。

對於最長不上公升子串行:模仿上面的定義,我們把s陣列的定義改為所有最長上公升子串行長度為d[i]時的a[i]的最大值,為什麼要是最大值呢?因為s陣列在這裡應該遵循嚴格的遞減序列才對,為了能夠檢索a[i],我們必須使得返回的下標一定就是d[i]的值,具體的實現方法:s的初始值賦為-inf,二分查詢的過程需要改一下,s陣列更新時使用max。

/*最長不上公升子串行 poj 1887*/

void init()

int bsearch(int x, int y, int v)

return x;} 

void dp()

printf("  maximum possible interceptions: %d\n", ans);

}

這裡的二分是檢索a[i]在s陣列中的下標,如果沒有任何數比a[i]小,那麼返回值應該是s當前陣列的長度+1,不下降子串行剛好相反。

最長不下降子串行的優化:

對於最長不下降子串行,對於我們發現,bsearch的過程相當於,對於乙個整數b來說,是求小於等於b的最後乙個元素的「下乙個下標」r是什麼?所以我們可以用到stl中的函式,upper_bound,這樣我們不必再去手寫二分,也就減少了一些**量。

/*核心***/

void dp()

printf("%d\n", ans);

}

最終,筆者還是不得不感嘆:乙個正確的二分查詢也是很難寫的。。。

對於的解決方案:

最長上公升子串行 O nlogn

題目描述 input 輸入乙個整數n 表示接下來有 n 個數輸入。output 輸出當前數列最長上公升子串行的長度。直接上 最長下降子串行 最長山峰序列都可以以該問題為母問題 進行延伸。include include using namespace std define max 1000 int s...

最長上公升子串行O nlogn

假設已經計算出的兩個狀態a和b滿足a a a b 且d a d b 則對於後續所有的狀態i 即i a且i b 來說,a並不會比b差 如果b滿足a b a i 的條件,a肯定也滿足,且二者的d值相同 但反過來卻不一定了,a滿足a a a i 的條件時,b卻不一定滿足。換句話說,如果我們只保留a,一定不...

最長上公升子串行O nlogn

最近在做單調佇列,發現了最長上公升子串行o nlogn 的求法也有利用單調佇列的思想。最長遞增子串行問題 在一列數中尋找一些數,這些數滿足 任意兩個數a i 和a j 若i 設dp i 表示以i為結尾的最長遞增子串行的長度,則狀態轉移方程為 dp i max,1 j 這樣簡單的複雜度為o n 2 其...