题目描述
设有由 n 个不相同的非负整数组成的数列,记为:b(1)、b(2)、……、b(n) 且 b(i)≠b(j)(i≠j),若存在 i1 < i2 < i3 < … < ie 且有 b(i1) < b(i2) < … < b(ie) ,则称为长度为 e 的不下降序列。程序要求,当原数列出之后,求出最长的不下降序列。
例如:13,7,9,16,38,24,37,18,44,19,21,22,63,15。例中 13,16,18,19,21,22,63 就是一个长度为 7 的不下降序列,同时也有 7 ,9,16,18,19,21,22,63 长度为 8 的不下降序列。
输入格式
第一行为一个正整数 n 。
第二行为 n 个非负整数序列,每个数不超过 10000 。
输出格式
输出一个正整数,为最长的不下降序列的长度。
样例数据
输入
14
13 7 9 16 38 24 37 18 4 19 21 22 63 15
输出
8
备注
【数据范围】
对于 30% 的数据,n≤1000;
对于 70% 的数据,n≤5000;
对于 100% 的数据,n≤100000;
其实题目也没有多么困难,最简单的当然是O(n^2)的复杂度,模拟。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
int ans,n,x;
int a[100010],f[100010];
int main()
{
memset(a,0,sizeof(a));
memset(f,0,sizeof(f));
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
f[i]=1; //f为序列长度,先全部初始化为1。
}
for(int i=n-1;i>=1;i--)
for(int j=n;j>=i+1;j--)
if(a[i]<a[j]&&f[j]+1>f[i]) //如果满足提议,f加1。
f[i]=f[j]+1;
ans=-1;
for(int i=1;i<=n;i++)
if(f[i]>ans)
ans=f[i]; //找到最长的不下降序列。
cout<<ans<<endl;
return 0;
}
代码当然是浅显易懂的没话说。
但是在有些问题上,O(n^2)的复杂度并不怎么讨好,需要复杂度更低的算法。
那么我们还有O(nlogn),嗯,不怕。
也不过就是加了个二分。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
int n,x,mid;
int a[10003];
int main()
{
a[0]=0;
int tail=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
int low=0,high=tail-1;
while(low<=high)
{
mid=(low+high)/2;
if(a[mid]>=x) //不符合题意,范围缩小。
high=mid-1;
else
low=mid+1; //符合题意,范围再扩大。
}
if(low>=tail)
tail++; //得到最大。
a[low]=x;
}
cout<<tail<<endl;
return 0;
}
当然也没有多难,>o<
——我认为return 0,是一个时代的终结。