最長上公升子串行LIS模板

2021-07-30 11:09:30 字數 2769 閱讀 1118

有兩種演算法複雜度為 o(n*logn) 和 o(n^2)

o(n^2)演算法分析如下: (a[1]...a[n] 存的都是輸入的數)

1、對於a[n]來說.由於它是最後乙個數,所以當從a[n]開始查詢時,只存在長度為1的上公升子串行;

2、若從a[n-1]開始查詢.則存在下面的兩種可能性:

(1)若a[n-1] < a[n] 則存在長度為2的上公升子串行 a[n-1]、a[n];

(2)若a[n-1] > a[n] 則存在長度為1的上公升子串行 a[n-1]或者a[n];

3、一般若從a[t]開始.此時最長上公升子串行應該是按下列方法求出的:

在a[t+1].a[t+2]… a[n]中.找出乙個比a[t]大的且最長的上公升子串行,作為它的後繼。

4、為演算法上的需要.定義乙個陣列dp[1 … n]記錄最長上公升子串行的長度,則:

dp[1] = 1;

dp[k] = max (dp[i]:1 <= i < k 且 a[i ]< a[k] 且 k != 1) + 1.

模板:

#includeusing namespace std;

#define eps 1e-7

#define clr(x) memset(x, 0, sizeof(x))

#define long long ll

#define double db

#define pi acos(-1.0)

const int inf = 0x3f3f3f3f;

const int mod=1000000007;

const int maxn = 10000000;

const int dx = ;

const int dy = ;

int a[maxn];

int dp[maxn];

int main()

dp[i] = tmp + 1;

}printf("%d\n", dp[n]);

}return 0;

}

最長上公升子串行的o(n*logn)演算法分析如下:

先回顧經典的o(n^2)的動態規劃演算法,設a[t]表示序列中的第t個數,dp[t]表示從1到t這一段中以t結尾的最長上公升子串行的長度,初始時設dp [t] = 0(t = 1, 2, ..., len(a))。則有動態規劃方程:dp[t] = max (j = 1, 2, ..., t - 1, 且a[j] < a[t])。

現在,我們仔細考慮計算dp[t]時的情況。假設有兩個元素a[x]和a[y],滿足

(1)x < y < t

(2)a[x] < a[y] < a[t]

(3)dp[x] = dp[y]

此時,選擇dp[x]和選擇dp[y]都可以得到同樣的dp[t]值,那麼,在最長上公升子串行的這個位置中,應該選擇a[x]還是應該選擇a[y]呢?

很明顯,選擇a[x]比選擇a[y]要好。因為由於條件(2),在a[x+1] ... a[t-1]這一段中,如果存在a[z],a[x] < a[z] < a[y],則與選擇a[y]相比,將會得到更長的上公升子串行。

再根據條件(3),我們會得到乙個啟示:根據dp的值進行分類。對於dp的每乙個取值k,我們只需要保留滿足dp[t] = k的所有a[t]中的最小值。設d[k]記錄這個值,即d[k] = min (dp[t] = k)。

注意到d的兩個特點:

(1) d[k]的值是在整個計算過程中是單調不上公升的。

(2) d的值是有序的,即d[1] < d[2] < d[3] < ... < d[n]。

利用d,我們可以得到另外一種計算最長上公升子串行長度的方法。設當前已經求出的最長上公升子串行長度為len。先判斷a[t]與d[len]。若a [t] > d[len],則將a[t]接在d[len]後將得到乙個更長的上公升子串行,len = len + 1, d[len] = a [t];否則,在d[1]..d[len]中,找到最大的j,滿足d[j] < a[t]。令k = j + 1,則有a [t] <= d[k],將a[t]接在d[j]後將得到乙個更長的上公升子串行,更新d[k] = a[t]。最後,len即為所要求的最長上公升子串行的長度。

在上述演算法中,若使用樸素的順序查詢在d[1]..d[len]查詢,由於共有o(n)個元素需要計算,每次計算時的複雜度是o(n),則整個演算法的時間複雜度為o(n^2),與原來的演算法相比沒有任何進步。但是由於d的特點(2),我們在d中查詢時,可以使用二分查詢高效地完成,則整個演算法的時間複雜度下降為o(nlogn),有了非常顯著的提高。需要注意的是,d在演算法結束後記錄的並不是乙個符合題意的最長上公升子串行!

模板

#includeusing namespace std;

#define eps 1e-7

#define clr(x) memset(x, 0, sizeof(x))

#define long long ll

#define double db

#define pi acos(-1.0)

const int inf = 0x3f3f3f3f;

const int mod=1000000007;

const int maxn = 10000000;

const int dx = ;

const int dy = ;

int a[maxn];

int dp[maxn];

int n, len, j;

int binsearch(int x)

}int main()

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

}return 0;

}

最長上公升子串行(LIS)(模板)

最長遞增子串行 longest increasing subsequence 下面我們簡記為 lis。假設存在乙個序列d 1.9 2 1 5 3 6 4 8 9 7,我們可以很輕鬆的看出來它的lis長度為5。但是如果乙個序列太長後,就不能直接看出來了!下面我們試著逐步找出答案。我們定義乙個序列b,然...

最長上公升子串行 LIS 模板

最長遞增 上公升 子串行問題 在一列數中尋找一些數,這些數滿足 任意兩個數a i 和a j 若i考慮兩個數a x 和a y x y且a x 按dp t k來分類,只需保留dp t k的所有a t 中的最小值,設d k 記錄這個值,d k min。這時注意到d的兩個特點 重要 1.d k 在計算過程中...

最長上公升子串行 LIS

題目 兩道題幾乎一樣,只不過對於輸入輸出的要求有所不同罷了。lis有兩種方法 一 第一種方法 時間複雜度為o n 2 狀態 dp i 區間為0 i的序列的lis 轉移方程 dp i max 1,dp k 1 0 k include include include include using name...