題目描述
現有數列a1,a2,a3……an。在其中找到嚴格遞增序列ai1,ai2,ai3,……aik(1 <= i1 < i2 < i3 < …… < ik <= n),請找出序列a的最長上公升子串行的長度,既k的最大值。
輸入格式
第一行:乙個整數n。
第二行:n個整數a1,a2,a3……an。
輸出格式
一行,最大的k。
輸入樣例
10510
89710
1312
2513
輸出樣例
6
提到dp,就一定就要去想:狀態、轉移方程、初值和答案了。
狀態:dp[i]指在1~i這i個數中,必須包含a[i]這個數的最長上公升子串行。
轉移方程:if(a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1)(1 <= j <= i - 1)
其實這個的意思就是:如果說在1~(i - 1)這(i - 1)個數中,a[j] < a[i],a[i]就可以接上a[j],形成乙個比dp[j]又多了1的遞增序列,因此每次判斷並取最大值就行了。
初值:dp[i] = 1(乙個數本身就是乙個遞增序列)。
答案:max
(ps:nr指序列長度的上限)
# include
# include
# include
# include
# include
using
namespace std;
# define for(i, a, b) for(int i = a; i <= b; i++)
# define _for(i, a, b) for(int i = a; i >= b; i--)
const
int nr =
100000
;int n, ans;
int a[nr +2]
, dp[nr +2]
;int
main()
printf
("%d\n"
, ans)
;return0;
}
二維動態規劃的時間複雜度為on^2,太多了,我們想去優化,可是我們發現直接在二維上改好像改不了,沒辦法,只好再想乙個新的方法了。
這次,我們開乙個新的陣列f,f[i]表示當上公升子串行長度為i時,此子串行最後乙個元素的最小值。我們會發現這個f陣列是隨著i值的增加,f[i]不斷增大的單調佇列。因為如果長度為i的上公升子串行最後一位都為f[i]了,那長度(i + 1)的最後一位至少也得是f[i] + 1了吧。
這樣我們從1到n乙個元素乙個元素的分析,當到了第i個元素時,我們在f陣列中找第乙個大於等於a[i]的f[k],這就代表長度為(k - 1)的上公升子串行最後一位的最少值是f陣列中最後乙個小於a[i]的數,所以就讓我們就可以把a[i]放到長度為(k - 1)的這個上公升子串行的後面,形成乙個新的長度為k的這個上公升子串行,接下來更新f[k]的值f[k] = min(f[k], a[i])可我們發現我們找f[k]時就說了f[k]是f陣列中第乙個大於等於a[i]的數,所以直接f[k] = a[i]就好了。
下圖僅供參考。
其中,在f陣列中找第乙個大於等於a[i]的f[k]時,可以用到二分查詢函式中的lower_bound函式。
如果你還沒有學過lower_bound可以到此**學習lower_bound函式的用法
這樣時間複雜度就從on^2降到了onlogn,大大減少了時間的消耗。
以下為**:
# include
# include
# include
# include
# include
using
namespace std;
# define for(i, a, b) for(int i = a; i <= b; i++)
# define _for(i, a, b) for(int i = a; i >= b; i--)
const
int nr =
100000
;int n, ans;
int a[nr +2]
;int f[nr +2]
;int
main()
printf
("%d\n"
, ans)
;return0;
}
剩下的這三種都與第一種十分相像:
ps:cmp函式的寫法:
bool
cmp(
int x,
int y)
最長上公升子串行 c
題目描述 輸入描述 輸入包含多組資料,每組資料第一行包含乙個正整數n 1 n 1000 緊接著第二行包含n個正整數m 1 n 10000 代表隊伍中每位隊員的身高。輸出描述 對應每一組資料,輸出最長遞增子串行的長度。解題思路 1 什麼是遞增子串行?例 有乙個序列 其中 等都是原序列的遞增子串行 注意...
最長上公升子串行
問題描述 乙個數的序列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...