• 单调递增子序列(二)


     

    单调递增子序列(二)

    时间限制: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

    二分法+动态规划

    #include<iostream>
    #include<cstdio>
    #include<cstring>

    using namespace std;

    int a[100002];
    int d[100002];
     /*int binarysearch(int num, int n)
     {
         for(int i = 1; i <= n; i++)
         {
             if(d[i] >= num)
                 break;
         }
         return i;
     }这是不用二分法的查找,o(n^2),会超时*/

     int binarysearch(int num, int len)
     {
         int left, right, mid;
         left = 1;
         right = len;
         mid = (left + right) / 2;
         while(left <= right)
         {
             if(d[mid] < num)
                 left = mid + 1;
             else if(d[mid] > num)
                 right = mid -1;
             else
                 return mid;
             mid = (left + right) / 2;
         }
         return left;
     }//o(nlogn)
     int main()
     {
         int n, len, i, j;
         while(scanf("%d", &n) != EOF)
         {
             for(i = 0; i < n; i++)
                 scanf("%d", &a[i]);
             memset(d, 0, sizeof(0));
             len = 1;
             d[1] = a[0];
             d[0] = -1000000;
             for(i = 1; i < n; i++)
             {
                 j = binarysearch(a[i], len);
                 d[j] = a[i];
                 if(j > len)
                     len = j;
             }
             printf("%d\n", len);
         }
         return 0;
     }

    高手的做法:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int MAX=100100;
    int num[MAX],top=0;

    int main()
    {    
     int n;
     
    while(~scanf("%d",&n))     
    {      
      scanf("%d",&num[0]);         
      top=1;        
     for(int i=1;i!=n;i++)       
     {
                
       scanf("%d",&num[i]);            
      int * p=lower_bound(num,num+top,num[i]);     //在有序区间中查找不小于某个值的元素       
      if(p-num==top) ++top;           
      *p=num[i];        
    }        
     printf("%d\n",top);    
    }
        
    }

  • 相关阅读:
    HDU 5744
    HDU 5815
    POJ 1269
    HDU 5742
    HDU 4609
    fzu 1150 Farmer Bill's Problem
    fzu 1002 HangOver
    fzu 1001 Duplicate Pair
    fzu 1150 Farmer Bill's Problem
    fzu 1182 Argus 优先队列
  • 原文地址:https://www.cnblogs.com/hpuwangjunling/p/2378567.html
Copyright © 2020-2023  润新知