• nyoj 214——单调递增子序列(二)——————【二分搜索加dp】


    单调递增子序列(二)

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:4
     
    描述

    给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度。

    如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。

     
    输入
    有多组测试数据(<=7)
    每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。
    数据以EOF结束 。
    输入数据保证合法(全为int型整数)!
    输出
    对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。
    样例输入
    7
    1 9 10 5 11 2 13
    2
    2 -1
    样例输出
    5
    1


    解题思路:这个题目看着跟求单调递增子序列(一)只是在数据范围上扩大了,其实在做法上也因此改变了。这个在n*log(n)的时间复杂度内是可以解决的,所以这里用到了一种别样的方式。在数组D中存放当前len值时符合条件的单调递增的子序列,每个D[]都是子序列的一个元素。每次在D中查找比当前输入的原始序列元素值大的最小值位置,返回下标。将该位置更新为输入元素,然后判断是否需要将len值增加。


    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100100;
    const int INF=1e9;
    int pos;
    int D[maxn];
    int BinSearch(int l,int r,int key){
        while(l<=r){
         //   printf("%d %d
    ",l,r);
            int mid=(l+r)/2;
            if(D[mid]<key){
                l=mid+1;
            }else if(D[mid]>key){
                r=mid-1;
            }else{
                return l;
            }
        }
        return l;
    }
    int main(){
        int n,i,j,k;
        while(scanf("%d",&n)!=EOF){
            scanf("%d",&pos);
            int len=1;
            D[0]=pos;
            for(i=1;i<n;i++){
                scanf("%d",&pos);
                j=BinSearch(0,len-1,pos);
        //        printf("%d....
    ",j);
                D[j]=pos;
                len=j+1>len?j+1:len;
            }
            printf("%d
    ",len);
        }
        return 0;
    }
    /*
    10
    2 3 5 7 4 6 8 9 11 12
    
    6
    2 3 1 1 6 8
    
    6
    8 9 4 5 6 3
    */
    

      







  • 相关阅读:
    十天冲刺之一
    每日日报2021 4/30
    每日日报2021 4/29
    每日日报2021 4/28
    每日日报2021 4/27
    每日日报2021 4/26
    每日日报2021 4/24
    每日日报2021 4/23
    《梦断代码》读后感
    273. Integer to English Words
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4505101.html
Copyright © 2020-2023  润新知