LIS最長上升子序列三種方法
O(n^2)的方法:
#include <iostream>
#include <stdio.h>#include <cstring>
#include <algorithm>
using namespace std;
int a[15010],dp[15010],front[15010];
int n;
int main()
{
scanf("%d",&n);
int maxn=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
dp[i]=1;
front[i]=-1;
for(int j=1;j<i;j++){
if(a[j]<a[i]){
dp[i]=max(dp[i],dp[j]+1);
front[i]=j;
}
}
maxn=max(maxn,dp[i]);
}
cout<<maxn<<endl;
return 0;
}
O(n log n)的方法:
二分:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
int n,a[20010],c[20010],len=0;
int Find(int x)
{
int l=1,r=len,mid;
while(l<=r){
mid=(l+r)>>1;
if(x>c[mid]){ //記憶方法:求上升序列,就表示x更大,那麼就是大於
l=mid+1;
}else r=mid-1;
}
return l;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
int k=Find(a[i]);
c[k]=a[i];
len=max(len,k);
}
printf("%d",len);
return 0;
}
STL 求最長上升子序列:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 1000
#define INF 2^32-1
int n;
int a[N],dp[N];
void solve()
{
fill(dp,dp+n,INF);
for(int i=0;i<n;i++)
*lower_bound(dp,dp+n,a[i])=a[i];
printf("%d\n",lower_bound(dp,dp+n,INF)-dp);
}
int main()
{
while(cin>>n){
for(int i=0;i<n;i++)
cin>>a[i];
solve();
}
return 0;
}