最長上公升子串行 II(LIS) 二分優化

2021-10-25 13:45:19 字數 1784 閱讀 3040

題目鏈結

思路

這題說是dp,但是分析完之後更像貪心了,首先舉個例子比如乙個序列:3 1 2 1 8 5 6。(後面下標從1開始計)那麼對於 a[1

]a [ 1 ]

a[1]

和 a[2]

a [ 2 ]

a[2]

來說,如果上公升子串行長度為2,那麼能接在 a[1

]a [ 1 ]

a[1]

後面的也一定能接在 a[2

]a [ 2 ]

a[2]

後面,因為a[2

]

1]

a [ 2 ] < a[ 1 ]

a[2]

1]。以此思想,引出我們 dpdp

dp陣列 f

ff 的狀態表示。

我們的狀態表示為 f[i

]f [ i ]

f[i]

存放的是所有長度為 i 的上公升子串行中所有末尾值中的最小值,這樣就能得到乙個嚴格的單調遞增序列,我們來證明一下為什麼嚴格單調遞增,假設 f[6

]≤f[

5]

f [ 6 ] ≤ f [ 5 ]

f[6]≤f

[5],那麼對於長度為6的這個上公升子串行來說,它的第五個數 t

tt 一定是小於 f[6

]f [ 6 ]

f[6]

的,那麼就存在 f[5

]>

tf [ 5 ] > t

f[5]

>

t ,但是我們存放的是所有長度為5的上公升子串行的末尾值中的最小值,所以矛盾了,故這個序列一定是單調遞增的。那麼對於 a[i

]a [ i ]

a[i]

我們只需要查詢 f

ff 陣列中小於 a[i

]a [ i ]

a[i]

的最大值 j

jj 即可,然後可以直接更新f[j

+1]=

a[i]

f [ j+1] = a [ i ]

f[j+1]

=a[i

],因為 a[i

]a [ i ]

a[i]

一定小於當前 f[j

+1

]f [ j + 1 ]

f[j+1]

,不然也不會找到 j

jj 了,那麼這個查詢到 j 的過程就是可以運用二分查詢來優化,所以整個演算法的時間複雜度就由樸素做法的o(n

²)

o(n²)

o(n²

)優化到o(n

logn

)o(nlogn)

o(nlog

n)。**

#include

using

namespace std;

const

int n =

1e6+5;

int a[n]

;int f[n]

;int n;

intmain()

f[0]

=-2e9;

//哨兵作用

int len=0;

for(

int i=

0;i) len=

max(len,r+1)

; f[r+1]

=a[i];}

printf

("%d\n"

,len)

;return0;

}

二分求最長上公升子串行

我們知道n2 求最長上公升子串行的方法,即 f i m ax f i f j 1 j 1i 1,f i f j 然而,我們可以用二分求最長上公升子串行。由於我們知道子串行c,c 1 c 2 c n 所以我們二分出乙個位置t,將c t 的值更新為a i 如果t ans,證明最長上公升子串行的長度可以 ...

二分求最長上公升子串行

二分求最長上公升子串行 求長度 之前在書上其實見到過,但是沒想去看,結果 回到正題,二分求最長上公升子串行的思路是,在原動態規劃寫法上進行優化,優化了查詢過程,使得查詢過程變成了lon2n,然後還用到了貪心,怎麼貪,就是保證原序列長度不變的情況下,讓裡面的元素盡可能小 當然滿足遞增 下面來驗證為什麼...

最長上公升子串行(貪心 二分)

最長上公升子串行的求法,除了最樸素的動態規劃外,還有利用貪心和二分法進行求解,其時間複雜度為o nlogn 低於動態規劃的時間複雜度o n2 在藍橋杯這種測試樣例巨大的競賽中,使用貪心 二分法可以有效避免超時 對於乙個數列a 我們定義乙個陣列s和陣列b,陣列b用來儲存可能的上公升序列。s i 表示長...