最長上公升子串行
時間限制: 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的下標比17、18、20都大,為什麼能插入呢?但是如果仔細想一想,這好像並不影響正常答案,但如果要輸出最長上公升子串行,那就要改一改這個演算法了。
整個二分查詢**如下:
else
a[l]=t;
}
由此,這個查詢演算法才得以下降到logn,於是,整體也就是o(nlogn)。具體操作如下:每次取棧頂元素和讀到的元素做比較,如果大於,則將它入棧;如果小於,則二分查詢棧中的比它大的第1個數,並替換它。最長序列長度即為最後模擬的大小。這也是很好理解的,對於i和j,如果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結尾的最長上公升子串行的長度,初始時...