lis問題是最經典的動態規劃基礎問題之一。
如果要求乙個滿足一定條件的最長上公升子串行,你還能解決嗎?
給出乙個長度為n整數序列,請求出它的包含第k個元素的最長上公升子串行。
例如:對於長度為6的序列<2,7,3,4,8,5>,它的最長上公升子串行為<2,3,4,5>,
但如果限制一定要包含第2個元素,那滿足此要求的最長上公升子串行只能是<2,7,8>了。
第一行為兩個整數n,k,如上所述。
接下來是n個整數,描述乙個序列。
請輸出兩個整數,即包含第k個元素的最長上公升子串行長度。
8 6
65 158 170 299 300 155 207 389
對於所有的資料,滿足0 < n <= 200000,0 < k <= n
題目都直接告訴你是dp了
直接將在 k 號元素之前的元素控制到只有比 a[k] 小的
之後的元素只有比他大的 a[k] 大的
然後分別求兩個最長上公升子串行,將所求的兩個長度相加再加一
下面來證明一下
k前面的所有比 a[k] 大的元素如果在最長上公升子串行裡,那麼 a[k]就不能取
與題設不符,後面的元素同理。所以為了有解,所有有他們存在的最長子序列都是錯誤的
如果我們不能取這些元素的話,就等價於把他們從原陣列刪掉
因為本身那個元素也在那個序列中,所以就要將最後的答案加一
最後因為題目資料範圍是200000,那麼用常規on^2的解法坑定要超時幾個點
那麼就需要用o nlogn 的解法,找後繼替換
想知道詳細證明過程的麻煩去看別的文章,這裡簡單解釋一下
定義s陣列,s[i]表示長度為i的最長上公升子串行的結尾元素的值。
但是長度為i的最長上公升子串行可能有很多個,應該儲存哪個序列的結尾元素呢?
顯然應該儲存最小的那個(可以用反證法證明)。這樣,s就是乙個遞增序列了
可以通過二分查詢來獲得乙個可以更新當前狀態的的最優值。這樣演算法就是nlogn的了。
#include
#include
#include
#include
using
namespace
std;
int n,k,len,ans=1;
int a[200005],b[200005],c[200005];
int main()
ans+=len,len=0;//更新答案,清零長度
for(int i=k+1;i<=n;++i)
ans+=len;
printf("%d\n",ans);
return
0;}
Dp 最長上公升子串 最長上公升子串行
乙個數的子串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,5,9 等等。這些子串中最長...
最長上公升子串行(DP)
time limit 3000ms memory limit 65536k 有疑問?點這裡 乙個數的序列bi,當b 1 b 2 b s的時候,我們稱這個序列是上公升的。對於給定的乙個序列 a 1,a 2,a n 我們可以得到一些上公升的子串行 a i1,a i2,a ik 這裡1 i 1 i 2 i...
最長上公升子串行 dp
description 乙個數的序列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...