最長上公升子串行

2021-09-01 22:41:56 字數 3892 閱讀 2001

最長上公升子串行

時間限制: 10 sec   記憶體限制:128 mb

題目描述

給定乙個序列,初始為空。現在我們將1到n的數字插入到序列中,每次將乙個數字插入到乙個特定的位置。我們想知道此時最長上公升子串行長度是多少?

輸入

第一行乙個整數n,表示我們要將1到n插入序列中,接下是n個數字,第k個數字xk,表示我們將k插入到位置xk(0<=xk<=k-1,1<=k<=n)

輸出

1行,表示最長上公升子串行的長度是多少。

樣例輸入

0 0 2

樣例輸出

提示

100%的資料 n<=10000

第乙個念頭就是用動態規劃,很顯然,這道題的轉移方程非常非常簡單,一目了然,先準備乙個陣列b

b[i]=1;

,從a[1]開始搜到i的最長上公升子串行。

這句賦值語句固然很好理解,每乙個元素,也可以視為乙個符合題意的子串行。

b[2]呢?

如圖,它顯然比a[1]高,在執行如下語句時

for(j=1;ja[j])

j小於i,也就是2,目前符合條件的只有a[1]a[1]又通過了判斷語句,它確實小於a[i]

b[i]=max(b[i],b[j]+1);

很顯然:b[2]顯然原來是1,當它和b[1]+1比時,1當然比2小,所以,b[2]自然就是2了。

再來看看時間複雜度:

很明顯,時間複雜度為o(n^2)

那,這個方法夠快嗎?還可以,但仍然有些不盡人意。

**如下o(n^2):

#includeusing namespace std;

int i,j,n,a[100],b[100],max;

int main()

for(max=i=0;imax) max=b[i];

cout<那麼,還有沒有更快的方法呢?

當然有,有沒有想到過,為什麼要記錄資料呢?

我們可以模擬乙個stack

在有大量資料的情況下,這演算法效率極高

但是,怎麼來優化程式呢?

我們可以這樣來模擬:

每輸入乙個數,如果這個數大於棧頂的那個數,於是把它推入棧中。

但是,如果這個數大於棧頂呢,這不證明它不可以更新棧中的

某個元素,這時,就可以運用二分查詢了。

有人可能會問:這個序列是無序的啊。沒錯,但查詢的是stack裡面的元素,而這個棧裡的所有元素,都是嚴格遞增的,所以,用二分查詢可以把問題縮減為o(nlogn)

有些不符合邏輯,不是嗎?15的下標比171820都大,為什麼能插入呢?但是如果仔細想一想,這好像並不影響正常答案,但如果要輸出最長上公升子串行,那就要改一改這個演算法了。

整個二分查詢**如下:

else

a[l]=t;

}

由此,這個查詢演算法才得以下降到logn,於是,整體也就是o(nlogn)具體操作如下:每次取棧頂元素和讀到的元素做比較,如果大於,則將它入棧;如果小於,則二分查詢棧中的比它大的第1個數,並替換它。最長序列長度即為最後模擬的大小。這也是很好理解的,對於ij,如果i**(同上):

#include using namespace std; 

int i,j,n,s,t,a[100001];

int main()

a[l]=t;}}

cout<

}

最長上公升子串行

問題描述 乙個數的序列bi,當b1 b2 bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列 a1,a2,an 我們可以得到一些上公升的子串行 ai1,ai2,aik 這裡1 i1 i2 ik n。比如,對於序列 1,7,3,5,9,4,8 有它的一些上公升子串行,如 1,7 3,4,8 等等...

最長上公升子串行

最長上公升子串行問題是各類資訊學競賽中的常見題型,也常常用來做介紹動態規劃演算法的引例,筆者接下來將會對poj上出現過的這類題目做乙個總結,並介紹解決lis問題的兩個常用 演算法 n 2 和 nlogn 問題描述 給出乙個序列a1,a2,a3,a4,a5,a6,a7.an,求它的乙個子串行 設為s1...

最長上公升子串行

最長上公升子串行問題 給出乙個由n個數組成的序列x 1.n 找出它的最長單調上公升子串行。即求最大的m和a1,a2 am,使得a1動態規劃求解思路分析 o n 2 經典的o n 2 的動態規劃演算法,設a i 表示序列中的第i個數,f i 表示從1到i這一段中以i結尾的最長上公升子串行的長度,初始時...