1. 程式人生 > 實用技巧 >CF340D Bubble Sort Graph&&Acwing896. 最長上升子序列 II

CF340D Bubble Sort Graph&&Acwing896. 最長上升子序列 II

題意

給你一個長度為n的序列,求這個序列的最長上升子序列的長度
n<=100000

先說一下樸素的動態規劃

即設\(f[i]\)表示以\(i\)為結尾的,最長上升子序列的長度

狀態轉移

\(if(a[j]<a[i]) f[i]=max(f[i],f[j]+1)\)

可以看出,樸素的動態規劃我們的時間複雜度是\(O(n^2)\)

時間複雜度肯定過不去,那麼我們考慮怎麼優化

不難發現,一個數會產生貢獻,僅當它排在一個比它小的數後面,

我們可以開一個棧來維護

當這個新加進去的這個數比棧頂的元素小時,我們直接加進去

否則我們貪心的想,為了讓其最長,小的數用的越多越好

所以我們就二分查詢一下這個比較小的數可以放在哪裡

將比它大的那個替換掉就好

時間複雜度\(O(nlogn)\)

程式碼

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main()
{
	int n;
	cin >> n;
	vector<int>arr(n+10);
	for (int i = 1; i <= n; ++i)cin >> arr[i];
	vector<int>stk;
	stk.push_back(arr[1]);
	for (int i = 2; i <= n; ++i)
	{
		if (arr[i] > stk.back())//如果該元素大於棧頂元素,將該元素入棧
			stk.push_back(arr[i]);
		else//替換掉第一個大於或者等於這個數字的那個數
			*lower_bound(stk.begin(), stk.end(), arr[i]) = arr[i];
	}
	cout << stk.size() << endl;
	return 0;
}
/*
例 n: 7
arr : 3 1 2 1 8 5 6

stk : 3

1 比 3 小
stk : 1

2 比 1 大
stk : 1 2

1 比 2 小
stk : 1 2

8 比 2 大
stk : 1 2 8

5 比 8 小
stk : 1 2 5

6 比 5 大
stk : 1 2 5 6

stk 的長度就是最長遞增子序列的長度

*/