最長遞增(上公升)子串行問題:在一列數中尋找一些數,這些數滿足:任意兩個數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]在計算過程中單調不公升;
2.d陣列是有序的,d[1]利用這兩個性質,可以很方便的求解:
1. 設當前已求出的最長上公升子串行的長度為len(初始時為1),每次讀入乙個新元素x:
2. 若x>d[len],則直接加入到d的末尾,且len++;(利用性質2)
否則,在d中二分查詢,找到第乙個比x小的數d[k],並d[k+1]=x,在這裡x<=d[k+1]一定成立(性質1,2)。
#include#includelis這種演算法的時間複雜度是o(nlogn),但是稍微難寫了一點。下面的是o(n^2),容易編寫。const
int n=1111
;int
d[n];
int bs(int a,int l,int r,int
key)
if(a[l]>=key) return l-1
;
returnl;}
int lis(int a,int
n)
return
len;
}int
main()
;
int tmp=lis(a,6
); printf(
"%d\n
",tmp);
for(int i=1;i<=tmp;i++)
printf(
"%d
",d[i]);
printf("\n
");return0;
}
1view codeint lis(int *a,intn)2
14}15}
16for(int i=1;i<=n;i++)
17if(dp[i]>ans)
18 ans=dp[i];
19return
ans;
20 }
參考文章:
最長上公升子串行LIS模板
有兩種演算法複雜度為 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 則...
最長上公升子串行(LIS)(模板)
最長遞增子串行 longest increasing subsequence 下面我們簡記為 lis。假設存在乙個序列d 1.9 2 1 5 3 6 4 8 9 7,我們可以很輕鬆的看出來它的lis長度為5。但是如果乙個序列太長後,就不能直接看出來了!下面我們試著逐步找出答案。我們定義乙個序列b,然...
最長上公升子串行 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...