描述
一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).
你的任务,就是对于给定的序列,求出最长上升子序列的长度。
输入
输入的第一行是序列的长度N。第二行给出序列中的N个整数。
输出
最长上升子序列的长度。
总结了四种方法:枚举O(2^n) ,动态规划O(n^2) ,数组维护+二分O(nlogn) ,线段树O(nlogn)
枚举code:
#include<bits/stdc++.h>
using namespace std;
int n,a[15],ans=0;
int s(int x,int l){
if(x==n) return 0;
if(a[x]>l) return max(s(x+1,a[x])+1,s(x+1,l));
return s(x+1,l);
}
int main() {
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n-1;i++){
ans=max(ans,s(i+1,a[i])+1);
}
cout<<ans<<endl;
return 0;
}
动态规划code:
include<bits/stdc++.h>
using namespace std;
int n,a[1010],f[1010],ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];f[i]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
}
ans=max(ans,f[i]);
}
cout<<ans<<endl;
return 0;
}
数组维护code:
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn=3e5+10;
int a[maxn],lst[maxn],f[maxn],n;
int main(){
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int ans=0;
for(int i=1;i<=n;i++){
f[i]=lower_bound(lst+1,lst+1+ans,a[i])-lst;
lst[f[i]]=a[i];
ans=max(ans,f[i]);
}
cout<<ans<<endl;
return 0;
}
线段树code:
#include<bits/stdc++.h>
#define endl '\n'
#define gcd __gcd
#define lson (p<<1)
#define rson (p<<1|1)
using namespace std;
typedef long long ll;
const int maxn=3e5+10;
struct T{
int l,r,mx;
}t[maxn<<2];
void build(int p,int l,int r){
t[p].l=l,t[p].r=r,t[p].mx=0;
if(l==r) return;
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
}
void change(int p,int x,int val){
if(t[p].l==t[p].r){
//cout<<t[p].l<<' '<<x<<endl;
t[p].mx=max(t[p].mx,val);
return;
}
int mid=t[p].l+t[p].r>>1;
if(x<=mid) change(lson,x,val);
if(x>mid) change(rson,x,val);
t[p].mx=max(t[lson].mx,t[rson].mx);
}
int query(int p,int l,int r){
if(l>r) return 0;
if(l<=t[p].l&&t[p].r<=r) return t[p].mx;
int mx=0,mid=t[p].l+t[p].r>>1;
if(mid>=l) mx=max(mx,query(lson,l,r));
if(r>=mid+1) mx=max(mx,query(rson,l,r));
return mx;
}
int n,a[maxn],v[maxn],ans;
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],v[i]=a[i];
build(1,1,n);
sort(v+1,v+1+n);
int m=unique(v+1,v+1+n)-v-1;
for(int i=1;i<=n;i++){
int x=lower_bound(v+1,v+1+m,a[i])-v;
int num=query(1,1,x-1)+1;
change(1,x,num);
ans=max(ans,num);
//cout<<query(1,1,1)<<endl;
}
//cout<<query(1,1,1)<<endl;
cout<<ans<<endl;
return 0;
}