Longest Increasing Subsequence

[FZU 1348]Longest Ordered Subsequence

Problem Description

A numeric sequence of ai is ordered if a1 < a2 < … < aN. Let the subsequence of the given numeric sequence ( a1, a2, …, aN) be any sequence ( ai1, ai2, …, aiK), where 1 <= i1 < i2 < … < iK <= N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8).
Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.

Input

The first line of input file contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 <= N <= 1000

Output

Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.

Sample Input

7
1 7 3 5 9 4 8

Sample Output

4

My Problem Report

这是一道LIS模板题,之前其实做过两次,但今天遇到一个类似的题目时却忘了算法,写份题解报告巩固下记忆。O(n^2)的算法就不说了,非常好写,这里主要整理一下靠 DP+二分查找 实现的 O(nlogn)算法。
这个算法重点在于理解其DP思想。在常规的O(n^2)算法中,我们记录了原串每个点作为单调序列结尾时所能构成的长度。但我们仔细想一想,这样做其实是没有必要的。下面举一个简单的例子来辅助说明:

原串:1 4 2 3
记录:1 2 2 3

对于3而言,它可以作为前面三个中任意一个数的后缀,但我们希望它能构成足够长的序列。这个时候我们发现,4对应点所记录的信息是没有任何意义的,因为它完全可以被2取代。
我们可以总结得到:对于一个点x而言,我们想要让它接到前面已定的Increasing Subsequence上,并且尽可能得长。假设我们构造好这个新的Increasing Subsequence(假设长度为len,记作s1)后发现,在之前就已经构造过一个长度为len的IS(记作s2),并且尾的尾部元素(记作x0)不比x大,那么我们就没有必要再记录s1了,因为在后续的扫描中,我们完全可以将新元素接到s2后面,甚至可能得到更优的结果。因为x0可能比x小,可能帮助我们构造更长的IS。
综上所述,我们用一个hash数组来记录“当前状态“下,已构造好的各个长度IS的末尾元素。在遍历原串的每一元素时,对它所构成的LIS进行更新(如果需要的话)。

hash[len]=tail

My Source Code

//  Created by Chlerry in 2015.
//  Copyright (c) 2015 Chlerry. All rights reserved.
//

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>

using namespace std;
#define Size 10010
#define ll long long
#define mk make_pair
#define pb push_back
#define mem(array, x) memset(array,x,sizeof(array))
typedef pair<int,int> P;

int a[Size],l[Size],r[Size];
int main()
{
    int n;
while(cin>>n && n)
{
    for(int i=1;i<=Size;i++)
         l[i]=r[i]=INT_MAX;
    for(int i=0;i<n;i++)
        cin>>a[i];
    l[1]=a[0];
    for(int i=1;i<n;i++)
    {
        int pos=lower_bound(l,l+n,a[i])-l;
        l[pos]=a[i];
    }
    cout<<lower_bound(l,l+n+1,INT_MAX)-l-1<<endl;
}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值