1134 最长递增子序列(时间复杂度O(n*log(n))

来源:互联网 发布:支付宝贷款软件 编辑:程序博客网 时间:2024/05/17 05:05

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

Description

给出长度为N的数组,找出这个数组的最长递增子序列。(递增子序列是指,子序列的元素是递增的)
例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10。

Input

第1行:1个数N,N为序列的长度(2 <= N <= 50000)
第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)

Output

输出最长递增子序列的长度。

Input示例

8
5
1
6
8
2
4
5
10

Output示例

5

举例:
数组 d[] = 2 1 5 3 6 4 8 9 7 (其中最长上升子序列长度为 5)
数组 B[] 最终的长度即为最长上升子序列的长度
d[1] = 2 –> B[1] = 2;
d[2] = 1 ( d[2] < B[1] ) –>B[1] = 1; B[] = 1
d[3] = 5 (d[3] > B[1]) –>B[2] = 5; B[] = 1 5
d[4] = 3 (d[4] < B[2]) –>B[2] = 3; B[] = 1 3
d[5] = 6 (d[5] > B[2]) –>B[3] = 6; B[] = 1 3 6
d[6] = 4 (d[6] < B[3]) –>B[3] = 4; B[] = 1 3 4
d[7] = 8 (d[7] > B[3]) –>B[4] = 8; B[] = 1 3 4 8
d[8] = 9 (d[8] > B[4]) –>B[5] = 9; B[] = 1 3 4 8 9
d[9] = 7 (d[9] < B[5]
&&d[9] < B[4]) –>B[4] = 7; B[] =1 3 4 7 9 所以长度为5;
注意::::数组B 中存放的元素并不一定是最长上升子序列的元素

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int n;int len;int d[500005],B[500005];//二分查找int search_bound(int i){    int left,right,mid;    left = 1,right = len;    while(left <= right)    {        mid = (left + right)/2;        if(B[mid] == d[i])            return mid;        else if(B[mid] > d[i])            right = mid-1;        else            left = mid+1;    }    return left;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&d[i]);    B[1] = d[1];  //先把第一个元素放入    len = 1;    for(int i=2;i<=n;i++)    {        if(d[i] > B[len])   //后一个比前一个大            B[++len] = d[i];    //直接放入数组        else  //否则二分查找返回下界        {            int pos = search_bound(i);            B[pos] = d[i];        }    }    printf("%d\n",len);    return 0;}

动态规划代码:O(n^2)

//超时代吗#include <iostream>#include <cstdio>#define Max 1001using namespace std;int main(){    int i, j, n, maxx;    // a[i]表示输入第i个元素    int a[Max];    // d[i]表示以a[i]结尾的最长子序列长度    int d[Max];    scanf("%d",&n);    for (i = 1; i <= n; i++)        scanf("%d",&a[i]);    maxx = 0;    for (i = 1; i <= n; i++)    {        d[i] = 1;        for (j = 1; j <= i - 1; j++)        {            if (a[j] < a[i] && d[i] < d[j] + 1)            {                d[i] = d[j] + 1;            }        }        // 记录最长子序列        if (d[i] > maxx)            maxx = d[i];    }    printf("%d\n",maxx);    return 0;}
阅读全文
0 0
原创粉丝点击