T1朴素的最长严格上升子序列

http://codevs.cn/problem/3955/

给一个数组a1, a2 ... an,找到最长的上升降子序列ab1<ab2< .. <abk,其中b1<b2<..bk。

输出长度即可。

输入描述 Input Description

第一行,一个整数N。

第二行 ,N个整数(N < = 1000000)

输出描述 Output Description

输出K的极大值,即最长严格上升子序列的长度

样例输入 Sample Input

5

9 3 6 2 7

样例输出 Sample Output

3

n²做法:f[i]=j表示以第i个数结尾的最长上升子序列长度为j

#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[5001],f[5001],ans;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        int maxn=0;
        for(int j=1;j<i;j++) 
         if(a[i]>a[j]&&maxn<f[j]) 
          maxn=f[j];
        f[i]=maxn+1;
        ans=max(f[i],ans);
    }
    printf("%d",ans);
}
View Code

nlogn做法:f[i]=表示长度为i的最长上升子序列中,第i个数最小是j,二分查找

#include<cstdio>
using namespace std;
int n,f[5001],s,x;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if(x>f[s]) 
        {
            f[++s]=x;
            continue;
        }
        int l=0,r=s,k;
        while(l<=r)
        {
            int m=l+r>>1;
            if(x>f[m]) 
            {
                l=m+1;    k=m;
            }
            else r=m-1;
        }
        if(f[k+1]>x) f[k+1]=x;
    }
    printf("%d",s);
}
View Code

 

T2 包含第k个数的最长上升子序列

 http://codevs.cn/problem/2188/

题目描述 Description

LIS问题是最经典的动态规划基础问题之一。如果要求一个满足一定条件的最长上升子序列,你还能解决吗?

    给出一个长度为N整数序列,请求出它的包含第K个元素的最长上升子序列。

    例如:对于长度为6的序列<2,7,3,4,8,5>,它的最长上升子序列为<2,3,4,5>,但如果限制一定要包含第2个元素,那么满足此要求的最长上升子序列就只能是<2,7,8>了。

输入描述 Input Description

第一行为两个整数N,K,如上所述。

    接下来是N个整数,描述一个序列。

输出描述 Output Description

请输出两个整数,即包含第K个元素的最长上升子序列长度。

样例输入 Sample Input

8 6

65 158 170 299 300 155 207 389

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

80%的数据,满足0<n<=1000,0<k<=n

    100%的数据,满足0<n<=200000,0<k<=n

把k前面大于等于第k个数的都删去,k后面小于等于第k个数的都删去,然后套上面的方法

#include<cstdio>
using namespace std;
int n,a[200001],f[200001],s,k,x;
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<k;i++) 
     if(a[i]>=a[k]) a[i]=-1;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==-1) continue;
        if(i>k&&a[i]<=a[k]) continue;
        if(a[i]>f[s]) 
        {
            f[++s]=a[i];
            continue;
        }
        int l=0,r=s,p=0;
        while(l<=r)
        {
            int m=l+r>>1;
            if(a[i]>f[m]) 
            {
                l=m+1;    p=m;
            }
            else r=m-1;
        }
        if(f[p+1]>a[i]) f[p+1]=a[i];
    }
    printf("%d",s);
}
View Code

相关文章: