51Nod 1134 最长递增子序列

给出长度为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

思路:一开始没想那么多,直接dp,后面发现超时了,查了下最长上升子序列的解法发现有一种模拟栈操作的解法,时间复杂度为O(nlogn).套一下板子就行了,主要还是理解这份模板如何运行的
自己用代码测了下,当输入的数>top是,加入栈中并设为top,当输入的数<top时,找到栈中第一个大于它的数字并替换掉,这样虽然长度没有变化,但他的”潜力“变大了。最后top就是子序列最大长度了
算法主要还是贪心思想,用二分缩短时间。

实现代码:
#include <iostream>

using namespace std;

int main()
{
    int i, j, n, top, temp;
    int stack[1001];
    while(cin >> n)
   {
    top = 0;
    stack[0] = -1199999999;
    for (i = 0; i < n; i++)
    {
        cin >> temp;
        /* 比栈顶元素大数就入栈 */
        if (temp > stack[top])
        {
            stack[++top] = temp;
        }
        else
        {
            int low = 1, high = top;
            int mid;
            /* 二分检索栈中比temp大的第一个数 */
            while(low <= high)
            {
                mid = (low + high) / 2;
                if (temp > stack[mid])
                {
                    low = mid + 1;
                }
                else
                {
                    high = mid - 1;
                }
            }
            /* 用temp替换 */
            stack[low] = temp;
        }
    }

    /* 最长序列数就是栈的大小 */
    cout << top << endl;
  }
    return 0;
}
原文地址:https://www.cnblogs.com/kls123/p/7783694.html