最长上升子序列

最长上升子序列

最长上升子序列是DP的入门题目,解法多样,只介绍\(nlog_n\)的做法。

其实nlogn的做法不是传统的DP而是贪心。

定理:如果当前已选子序列的最后一位ans[last]有更合适的选择,则该选择a[i]满足\(ans[last - 1]< a[i] < ans[last]\),所以可以用二分优化查找,来更新已选子序列。

/*#include <bits/stdc++.h>
using namespace std;
int n, data[100010], dp[1001000];
int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d", &data[i]), dp[i] = 2147483647;
	for (int i = 1; i <= n; i++)
		*lower_bound(dp + 1, dp + 1 + n, data[i]) = data[i];
	printf("%d", lower_bound(dp + 1, dp + 1 + n, 2147483647) - (dp + 1));
	return 0;
} 	
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100100;
int a[maxn], n, lis[maxn], len;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i = 1; i <= n; i++) cin>>a[i];
    lis[++len] = a[1];
    for(int i = 2; i <= n; i++)
    {
        if(a[i] > lis[len])
            lis[++len] = a[i];
        if (a[i] < lis[len])
        {
            int pos = lower_bound(lis+1, lis+1+len, a[i]) - lis;//找到第一个比a[i]大的数 
            lis[pos] = a[i];
        }
    }
    for(int i = 1; i <= len; i++) cout<<lis[i]<<" ";
    cout<<endl;
    cout<<len; 
    return 0; 
}
posted @ 2019-07-17 20:18  DAGGGGGGGGGGGG  阅读(188)  评论(0编辑  收藏  举报