題目描述
設有由 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,是一個時代的終結。