hdu3998 Sequence(最长上升子序列及其个数)

Description

There is a sequence X (i.e. x[1], x[2], ..., x[n]). We define increasing subsequence of X
as x[i1], x[i2],...,x[ik], which satisfies follow conditions:
1) x[i1] < x[i2],...,<x[ik];
2) 1<=i1 < i2,...,<ik<=n

As an excellent program designer, you must know how to find the maximum length of the
increasing sequense, which is defined as s. Now, the next question is how many increasing
subsequence with s-length can you find out from the sequence X.

For example, in one case, if s = 3, and you can find out 2 such subsequence A and B from X.
1) A = a1, a2, a3. B = b1, b2, b3.
2) Each ai or bj(i,j = 1,2,3) can only be chose once at most.

Now, the question is:
1) Find the maximum length of increasing subsequence of X(i.e. s).
2) Find the number of increasing subsequence with s-length under conditions described (i.e. num).

Input

The input file have many cases. Each case will give a integer number n.The next line will
have n numbers.

Output

The output have two line. The first line is s and second line is num.

Sample Input

4
3 6 2 5

Sample Output

2
2

题意:给你一个序列,求此序列的最长上升子序列的值s以及值为s的最长上升子序列的个数;

思路:求出最长上升子序列的值s后将原数组中的这些数删除,然后再次求最长上升子序列,重复操作,一直到所求得的最长上升子序列的值不等于s。如何删除原数组的数,
只需要用一个标记数组记录一下哪些数已经用过了就可以了;

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#define INF 0x3f3f3f3f
#define N 1000
using namespace std;
int b[N],a[N],dp[N],n;
int maxlen()
{
    int i,res,k=-1;
    for(i=0; i<n; i++)
    {
        if(b[i])//如果当前数已经选取过了,跳过;
            continue;
        *lower_bound(dp,dp+n,a[i])=a[i];
        int d=lower_bound(dp,dp+n,a[i])-dp;
        if(d>k)//使用二分查找插入的位置应该满足大于k才可以进行标记,避免标记多余的数;另外由于d最小是0,所以k应当从-1开始;(单步调试一下很容易就能明白了)
        {
            b[i]=1;
            k++;
        }
    }
    res=lower_bound(dp,dp+n,INF)-dp;
    return res;
}
int main()
{
    int i,answer,ans;
    while(~scanf("%d",&n))
    {
        memset(b,0,sizeof(b));
        memset(a,0,sizeof(a));
        for(i=0; i<n; i++)
            scanf("%d",&a[i]);
        int num=1;
        fill(dp,dp+n,INF);
        ans=maxlen();
        while(1)
        {
            fill(dp,dp+n,INF);
            answer=maxlen();
            if(answer!=ans)
                break;
            else
                num++;
        }
        printf("%d\n%d\n",ans,num);
    }
    return 0;
}



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值