第一种模板(常规模板),时间复杂度O(n2)。
#include<iostream>
using namespace std;
int a[1024],dp[1024];
int main()
{
int n=0,ans=0;
while(cin>>a[n++]);n--;
dp[0]=1;
for(int i=1;i<n;i++){
dp[i]=1;
for(int j=0;j<i;j++)
if(a[i]>a[j])
dp[i]=dp[i]>dp[j]+1?dp[i]:dp[j]+1;
ans=ans>dp[i]?ans:dp[i];
}
cout<<ans<<endl;
}
第二种写法(二分法模板),时间复杂度O(nlogn)
#include<iostream>
using namespace std;
int a[1024],dp[1024];
int main()
{
int n=0,ans=0;
while(cin>>a[n++]);n--;
int len=0;
for(int i=0;i<n;i++){
int l=0,r=len,mid;
if(dp[len]<a[i]) dp[++len]=a[i];
else {
while(l<r){
mid=l+r>>1;
if(dp[mid]<a[i])
l=mid+1;
else
r=mid;
}
dp[l]=a[i];
}
}
cout<<len<<endl;
}
例题:P1020 [NOIP1999 普及组] 导弹拦截 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
答案:
#include<iostream>
#include<string.h>
using namespace std;
//求最长上升子序列
int a[100001];
int main()
{
int n=0;
while(scanf("%d",&a[n++])!=EOF);
n--;
int dp[100001],len=0;
dp[0]=0x7fffffff;
for(int i=0;i<n;i++){
int l=0,r=len;
if(a[i]<=dp[len]) dp[++len]=a[i];
else {
while(l<r){
int mid=l+r>>1;
if(a[i]<=dp[mid]) l=mid+1;
else r=mid;
}
dp[l]=a[i];
}
}
cout<<len<<endl;
len=0;
dp[0]=-1;
for(int i=0;i<n;i++){
int l=0,r=len;
if(a[i]>dp[len]) dp[++len]=a[i];
else {
while(l<r){
int mid=l+r>>1;
if(a[i]>dp[mid]) l=mid+1;
else r=mid;
}
dp[l]=a[i];
}
}
cout<<len;
}