lis問題是經典的動態規劃問題,它的狀態轉移相信大家都很熟悉:
f[i] = f[k] + 1 (k < i 且 a[k] < a[i])
顯然這樣做複雜度是o(n^2)
有沒有更快的演算法呢?
當然,你會發現你在往前找的過程中實際上就是在查詢最大值的過程,如果能應用二分就很有機會降到nlogn
但是原f序列並不滿足二分性質吶。。怎麼辦呢?
我們要的是往前長度最大的,我們的二分目標就是長度
不妨開乙個長度陣列len[i],表示長度為i的上公升子串行最後末尾的值的最小值
對於沒算出的len,設為inf,每次算完f[i]後,就對len[f[i]]進行更新
這樣子我們就可以每次logn算出f[i]
為什麼這樣是正確的呢?
應為len陣列是單調遞增的,長度為2的末尾值一定比長度為3的要小,所以我們寫的二分一定是最大值的二分
fill(len,len + maxn,inf);
len[0] = 0;
int ans = 0;
rep(i,n)
f[i] = l + 1;
len[f[i]] = min(len[f[i]],a[i]);
ans = max(ans,f[i]);
} cout<
最長上公升子串行nlogn演算法
這題目是經典的dp題目,也可叫作lis longest increasing subsequence 最長上公升子串行 或者 最長不下降子串行。很基礎的題目,有兩種演算法,複雜度分別為o n logn 和o n 2 a.o n 2 演算法分析如下 a 1 a n 存的都是輸入的數 1 對於a n 來...
最長上公升子串行nlogn演算法
定義d k 長度為k的上公升子串行的最末元素,若有多個長度為k的上公升子串行,則記錄最小的那個最末元素。注意d中元素是單調遞增的,下面要用到這個性質。首先len 1,d 1 a 1 然後對a i 若a i d len 那麼len d len a i 否則,我們要從d 1 到d len 1 中找到乙個...
最長上公升子串行nlogn演算法
這題目是經典的dp題目,也可叫作lis longest increasing subsequence 最長上公升子串行 或者 最長不下降子串行。很基礎的題目,有兩種演算法,複雜度分別為o n logn 和o n 2 a.o n 2 演算法分析如下 a 1 a n 存的都是輸入的數 1 對於a n 來...