[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;
}